1

I created a compound view TextViewWithSub with 2 TextViews basically following the tutorial Creating Compound Views on Android. The only major difference seems to be that I am using this within a fragment instead of an activity, which may or may not be part of the problem.

I can access all widgets from the fragments onCreateView except my custom compound view. If I don't try to access that everything works and the compound view is correctly initialized and displayed.

I also checked that initializeViews on my custom component is executed before I try to access it, so I do not unterstand why findViewById returns null.

Fragment onCreateView:

    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        final View view = inflater.inflate(R.layout.activity_vector_detail, container, false);

        ((TextView)view.findViewById(R.id.testLbl)).setText("foobar"); // works
        ((TextViewWithSub)view.findViewById(R.id.directionLbl)).setMainText("foobar"); // NullPointerException here

        return view;
    }

activity_vector_detail.xml contains these widgets:

<TextView
    android:text="TextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/testLbl"/>

<my.namespace.TextViewWithSub
    android:id="@+id/directionLbl"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"/>

Custom Compound Class:

public class TextViewWithSub extends RelativeLayout {

    public TextViewWithSub(Context context) {
        super(context);
    }

    public TextViewWithSub(Context context, AttributeSet attrs) {
        super(context);
        initializeViews(context, attrs);
    }

    public TextViewWithSub(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initializeViews(context, attrs);
    }

    public void setMainText(CharSequence text) {
        ((TextView)this.findViewById(R.id.mainText)).setText(text);
    }

    public void setSubText(CharSequence text) {
        ((TextView)this.findViewById(R.id.subText)).setText(text);
    }

    private void initializeViews(Context context, AttributeSet attrs) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.textview_sub, this);

        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.TextViewWithSub);

        ((TextView)this.findViewById(R.id.mainText)).setText(a.getText(R.styleable.TextViewWithSub_mainText));
        ((TextView)this.findViewById(R.id.subText)).setText(a.getText(R.styleable.TextViewWithSub_subText));

        a.recycle();
    }
}

textview_sub layout:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
        android:id="@+id/mainText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

    <TextView
        android:id="@+id/subText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</merge>

Stacktrace:

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: my.namespace.App, PID: 10667
                  java.lang.NullPointerException: Attempt to invoke virtual method 'void my.namespace.TextViewWithSub.setMainText(java.lang.CharSequence)' on a null object reference
                      at my.namespace.activities.VectorDetail.onCreateView(VectorDetail.java:20)
                      at android.support.v4.app.Fragment.performCreateView(Fragment.java:2184)
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1298)
                      at android.support.v4.app.FragmentManagerImpl.moveFragmentsToInvisible(FragmentManager.java:2323)
                      at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2136)
                      at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2092)
                      at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1998)
                      at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:709)
                      at android.os.Handler.handleCallback(Handler.java:751)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:154)
                      at android.app.ActivityThread.main(ActivityThread.java:6119)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

Any help appreciated, Thanks!

Giovanni R
  • 11
  • 2
  • 1
    Possible duplicate of [What is a NullPointerException, and how do I fix it?](http://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – Code-Apprentice Jan 22 '17 at 04:34
  • Please post the stack trace and indicate which line causes the error. – Code-Apprentice Jan 22 '17 at 04:35
  • What is line 20 of VectorDetail.java? – Code-Apprentice Jan 22 '17 at 04:44
  • The one I have pointed out in onCreateView: `((TextViewWithSub)view.findViewById(R.id.directionLbl)).setMainText("foobar"); // NullPointerException here` – Giovanni R Jan 22 '17 at 04:46
  • try incorporating both the widgets in Single ViewGroup – Tulsi Jan 22 '17 at 05:02
  • My apologies. I missed the comment. I suggest breaking these lines up to help with debugging. Set a variable to the return value of `findViewById()` the call methods on the variable. When you do this, you can use a debugger to see the value of the variable and then go from there to figure out what is going on. – Code-Apprentice Jan 22 '17 at 05:10

1 Answers1

0

I have found the problem, stupid mistake, sorry:

public TextViewWithSub(Context context, AttributeSet attrs) {
    super(context);
    initializeViews(context, attrs);
}

Constructor was missing attrs when calling super, this works

public TextViewWithSub(Context context, AttributeSet attrs) {
    super(context, attrs);
    initializeViews(context, attrs);
}

although I don't really know why this leads to a NullPointerException when the widget works fine in any other way...

Giovanni R
  • 11
  • 2
  • 1
    The reason that was failing is because the `AttributeSet` contains the ID that's assigned to the `View` when it's inflated. Without that, your `TextViewWithSub` instance was ending up with an ID of `0`, and `view.findViewById(R.id.directionLbl)` was returning null. Just FYI. – Mike M. Jan 22 '17 at 05:31