将layout_weight分配给微调器时,微调器上的SetSelection崩溃

时间:2016-04-06 09:33:08

标签: android android-layout android-spinner android-layout-weight

我做了一个简化的实验来确定我遇到这个问题的地方。这是一个很长的问题,前面有很多代码。现在我保留了一个简单的小代码:

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.

这是错误:

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)

出现此错误是因为我设置了layout_width = 0dp。但同时layout_weight = 1。 注意:当setSelection(0)时,微调器正确膨胀。所以问题不在于直接通货膨胀。

这是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" />

如果layout_width =任何非零dp或match_parent或wrap_content ,则没有layout_weight ,整个代码完美无缺

但是使用上面相同的布局,以下代码可以正常工作,没有崩溃:

    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);

因此,我可以得出结论,我所做的ProfileSpinnerAdapter类存在一些与layout_weight = 1和width = 0dp相冲突的问题

这是适配器:

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;
}
}

错误的原因在于适配器。 如果微调器宽度= 100dp 则不会出错,并且只有在将微调器上放置layout_weight属性时才会出错

6 个答案:

答案 0 :(得分:6)

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

更改为

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

我也有这个问题并解决了

答案 1 :(得分:3)

我已经解决了以编程方式将TextView放在布局组中的问题:

@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;
}

同样有趣的是,在我将this numberpicker库包含到我的项目中之后发生了崩溃。我不知道库和崩溃之间的连贯性是什么,但如果我将其排除,崩溃就会再次消失。

我还发现了一个相关的android issue。提供的原因是:由于TextView未包装在ViewGroup中,因此与视图的任何交互都会导致应用程序因空指针异常而崩溃。 TextView正在尝试测量一些ViewGroup.LayoutParams。

答案 2 :(得分:2)

android:layout_width="0dp"设置为TextView,并根据您的要求为其提供layout_weight

答案 3 :(得分:0)

我认为这是因为您在使用此线性布局的权重时也设置了TextView宽度

  

机器人:layout_width = “80dp”

设置TextView width 0dp并赋予权重。

  

机器人:layout_width = “0dp”

     

android:layout_weight =“0.25”//根据总重量

您必须为此线性布局的所有子视图分别赋予权重,并为所有子视图设置宽度0dp。

希望这对你有用......

答案 4 :(得分:0)

作为一种解决方法,我使用了percentrelativelayout而不是layout_weight。可以通过将compile 'com.android.support:percent:23.2.0'添加到build.gradle中的依赖项来包含该库。

以下是我如何使用它。它完全按照我的意愿工作。 *我删除了不必要的xml属性。

    <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>

答案 5 :(得分:0)

也许已经晚了,但这就是我处理问题的方式。当我想将屏幕划分为两个相等的部分并且一个部分是微调器时,出现了此错误。因此,我使用了

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

组合。它在某些设备上可以正常工作,但是某些设备会抛出该异常。然后,将android:weightSum="2"赋予父级布局。然后问题就解决了。