5

I have done a simplified experiment to identify where I am having this problem. It was a long question with a lot of code earlier. Now I have kept a small and simple code:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_spinner_test);

    Spinner spin1 = (Spinner) findViewById(R.id.spin1);
    spin1.setAdapter(new ProfileSpinnerAdapter(this, R.array.feet));
    spin1.setSelection(0);  //does not crash
    spin1.setSelection(getResources().getStringArray(R.array.feet).length - 1);  //it crashes
   //it crashes for any value greater than 0 and less than array length.

This is the error:

java.lang.NullPointerException: Attempt to read from field 'int android.view.ViewGroup$LayoutParams.width' on a null object reference
    at android.widget.TextView.checkForRelayout(TextView.java:6830)
    at android.widget.TextView.onRtlPropertiesChanged(TextView.java:8948)
    at android.view.View.resolveRtlPropertiesIfNeeded(View.java:13118)
    at android.view.View.measure(View.java:17557)
    at android.widget.Spinner.setUpChild(Spinner.java:657)
    at android.widget.Spinner.makeView(Spinner.java:610)
    at android.widget.Spinner.getBaseline(Spinner.java:456)
    at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1294)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:615)
    at android.view.View.measure(View.java:17562)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5536)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
    at android.view.View.measure(View.java:17562)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5536)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
    at android.view.View.measure(View.java:17562)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5536)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
    at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2871) 
    at android.view.View.measure(View.java:17562)
    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2015)
    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1173)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1379)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5891)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
    at android.view.Choreographer.doCallbacks(Choreographer.java:580)
    at android.view.Choreographer.doFrame(Choreographer.java:550)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5294)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)

This error comes because I have set the layout_width=0dp. But at the same time layout_weight = 1. NOTE: The spinner is properly inflated when setSelection(0). So the problem is not with straight forward inflation.

Here is the xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context="in.jiyofit.the_app.SpinnerTestActivity">

<Spinner
    android:id="@+id/spin1"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1" />

The entire code works perfectly if layout_width = Any non zero dp or match_parent or wrap_content while there is no layout_weight.

But with the same above layout the following code works correctly with no crashes:

    Spinner spin1 = (Spinner) findViewById(R.id.spin1);
    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
            R.array.feet, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spin1.setAdapter(adapter);
    spin1.setSelection(getResources().getStringArray(R.array.feet).length - 1);

Thus I can conclude that there is some problem with the ProfileSpinnerAdapter class that I have made which conflicts with layout_weight = 1 and width = 0dp

Here is the adapter:

public class ProfileSpinnerAdapter extends BaseAdapter {
String[] array;
Context ctx;

public ProfileSpinnerAdapter(Context context, int arrayID) {
    this.ctx = context;
    this.array = ctx.getResources().getStringArray(arrayID);
}

@Override
public int getCount() {
    return array.length;
}

@Override
public Object getItem(int position) {
    return array[position];
}

@Override
public long getItemId(int position) {
    return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    TextView textView = new TextView(ctx);
    textView.setText(array[position]);
    textView.setTextSize(16);
    if(array[position].length() > 6){
        Typeface hindiFont = Typeface.createFromAsset(ctx.getAssets(),"fonts/mfdev010.ttf");
        textView.setTextSize(22);
        textView.setTypeface(hindiFont);
    }
    if(position == 0){
        textView.setTextColor(ContextCompat.getColor(ctx, R.color.primaryText));
    }
    return textView;
}

@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
    TextView textView = new TextView(ctx);
    textView.setText(array[position]);
    textView.setTextSize(16);
    textView.setPadding(0, 5, 0, 0);
    if(array[position].length() > 6){
        Typeface hindiFont = Typeface.createFromAsset(ctx.getAssets(),"fonts/mfdev010.ttf");
        textView.setTextSize(22);
        textView.setTypeface(hindiFont);
        textView.setPadding(10,5,10,5);
    }
    textView.setBackgroundColor(ContextCompat.getColor(ctx, R.color.white));
    textView.setTextColor(ContextCompat.getColor(ctx, R.color.primaryText));
    textView.setGravity(Gravity.CENTER);
    /*
    the adapter fills the number of elements based in the getCount
    so either getCount returns value conditionally for an array of different size in getDropDownView
    or the requisite value at position is hidden
    */
    if(position == 0){
        textView.setVisibility(View.GONE);
        textView.setHeight(0);
    }
    return textView;
}
}

The cause for the error is in the adapter. It gives no error if spinner width = 100dp and only gives error when layout_weight attribute is put on the spinner

bendaf
  • 2,981
  • 5
  • 27
  • 62
suku
  • 10,507
  • 16
  • 75
  • 120

6 Answers6

6
spin1.setSelection(0);  //does not crash
spin1.setSelection(getResources().getStringArray(R.array.feet).length - 1); 

change to

spin1.setSelection(0, true); 
spin1.setSelection(getResources().getStringArray(R.array.feet).length - 1, true); 

I also had this question and solved

Jihan Lin
  • 76
  • 1
  • 1
  • Can provide an explanation? – suku Aug 11 '16 at 04:47
  • I'm not sure why, but this fixes the problem when having Spinner with weight. Can it be because by setting animate=true it waits until the spinner is fully drawn? – dleal Sep 01 '16 at 17:20
  • had this issue when setEnabled was true, it also needs setselection to have true, works normal if its not setEnabled. – Mal Dec 01 '16 at 05:57
3

I have solved the problem with putting the TextView in a layout group programatically:

@Override
public View getView(int position, View arg1, ViewGroup arg2){

    ...

    // without this rtl the app crashes on lollipop devices with shawnlin number-picker
    RelativeLayout rtlContainer = new RelativeLayout(mContext);
    rtlContainer.addView(textView);
    return rtlContainer;
}

Also interesting, that the crash occurred after I included this numberpicker library to my project. I don't know what is the coherence between the library and the crash, but if I exclude it, the crash disappear again.

Also I found a related android issue. The reason provided is: Since the TextView is not wrapped in a ViewGroup, any interaction with the view causes the application to crash with a null pointer exception. The TextView is trying to measure some ViewGroup.LayoutParams.

suku
  • 10,507
  • 16
  • 75
  • 120
bendaf
  • 2,981
  • 5
  • 27
  • 62
  • 1
    Thanks. Spent a lot of time to findout the issue. Just this info, solve my issue on crashing the app. But will need to test for later Android (6, 7) and the lower than 5 to be sure. – Osify Oct 08 '16 at 11:20
  • I have tested it from Android SDK 18 till SDK 23 – bendaf Oct 09 '16 at 12:18
2

Set android:layout_width="0dp" to TextView and give layout_weight to it as per your requirement.

Murli Prajapati
  • 8,833
  • 5
  • 38
  • 55
  • My need is to give the textView a fixed width, which I have given. It is the width of the spinner that is giving the error – suku Apr 06 '16 at 10:13
  • I dont think that is possible as `layout_weight` doesn't work that way. Look at here [link](http://stackoverflow.com/a/3996044/5271656) – Murli Prajapati Apr 06 '16 at 11:30
  • Layout_weight only works on remaining area, not total area. checkout this video https://www.youtube.com/watch?v=rMksRBvYG28 . – suku Apr 06 '16 at 11:41
  • What I want to say is you cant use layout_weight on single child of parent view group. All children must have layout_weight attribute. You can give your text view a fixed width with appropriate weight. – Murli Prajapati Apr 06 '16 at 11:50
  • yes you can give width to a child layout as long as it does not have layout_weight. layout_weight overrides any width given. Hence android studio recommends 0dp width be given. – suku Apr 06 '16 at 12:02
0

I think this is happens because as you are using weight for this Linear Layout and also you set the TextView width

android:layout_width="80dp"

set TextView width 0dp and give weight.

android:layout_width="0dp"

android:layout_weight="0.25" //according to total weight

You have to give separate weight for all sub views of this Linear layout and also set width 0dp for all sub views.

Hope this will work for you...

Community
  • 1
  • 1
Vishal Chauhan
  • 932
  • 1
  • 6
  • 11
0

As a workaround, instead of layout_weight, I have used percentrelativelayout. The library can be included by adding compile 'com.android.support:percent:23.2.0' to the dependencies in build.gradle.

Here is how I used it. It works exactly as I want. *I have removed unnecessary xml attributes.

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:text="@string/aprofile_height" />

        <android.support.percent.PercentRelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <Spinner
                android:id="@+id/aprofile_dd_feet"
                app:layout_widthPercent="50%"
                android:layout_height="wrap_content" />

            <Spinner
                android:id="@+id/aprofile_dd_inches"
                app:layout_widthPercent="50%"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"/>

        </android.support.percent.PercentRelativeLayout>

    </LinearLayout>
suku
  • 10,507
  • 16
  • 75
  • 120
0

Maybe it is late, but this is how I handle the problem. I had this error when I want to divide screen two equal parts and one part is spinner. Therefore I have used

android:layout_weight="1"
android:layout_width="0dp"

combination. It works fine on some devices, but some devices throw that exception. Then I give android:weightSum="2" to the parent layout. Then the problem has been solved.

misman
  • 1,347
  • 3
  • 21
  • 39