<include>中的Switchbox在配置更改时自行设置

时间:2015-08-05 00:30:52

标签: android android-layout android-fragments

当我在switchboxes代码中使用<include>时,我遇到了非常奇怪的行为。最小的例子:

activity_main.xml中

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:id="@+id/fragment"
          android:name="com.fimagena.myapplication.MainActivityFragment"
          tools:layout="@layout/fragment_main"
          android:layout_width="match_parent"
          android:layout_height="match_parent"/>

fragment_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include android:id="@+id/inc1" layout="@layout/includelayout" />
    <include android:id="@+id/inc2" layout="@layout/includelayout" />
    <include android:id="@+id/inc3" layout="@layout/includelayout" />
</LinearLayout>

includelayout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <Switch
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Switch"
        android:id="@+id/switch1"
        android:layout_gravity="center_horizontal"/>
</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

MainActivityFragment.java

public class MainActivityFragment extends Fragment {

    @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_main, container, false);

        ((Switch) root.findViewById(R.id.inc1).findViewById(R.id.switch1)).setChecked(false);
        ((Switch) root.findViewById(R.id.inc2).findViewById(R.id.switch1)).setChecked(false);
        ((Switch) root.findViewById(R.id.inc3).findViewById(R.id.switch1)).setChecked(false);

        return root;
    }
}

我期望的是:一个带有3个开关的空片段,它们总是在配置更改时自行重置以取消选中(因为Activity和Fragment会被重建。)

我得到的是:当配置发生变化时(即旋转手机时),3个开关始终将自身重置为第3个开关所处的状态。

这是一个错误还是我错过了什么?鉴于我在所有3个交换机上明确使用setChecked(false),它们无论如何都不能将自己设置为on。配置更改正常,重建ActivityFragment,按预期调用onCreateView()。然而,所有3个开关的状态由最后一个开关确定,而不是由我的setChecked()电话确定。

我认为它与所有交换机具有相同ID的事实有关,因为它们包含在同一XML中。虽然我们可以正确识别它们,例如,我可以在一台交换机上呼叫setEnabled(),但只有该交换机受到影响。

1 个答案:

答案 0 :(得分:0)

我从未遇到过这个问题,因为我通常在布局中使用不同的ID。我认为问题在于Android通过其ID在内部维护视图状态。

您对所有支票使用相同的ID,因此您需要自己保存/恢复其状态。要小心,您必须恢复onViewStateRestored内的视图状态。这将确保您的视图状态不被系统覆盖。以下代码段应该可以使用。

<强> MainActivityFragment.java

package com.example.testapp;

import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Switch;

public class MainActivityFragment extends Fragment
        implements CompoundButton.OnCheckedChangeListener {
    private static final String TAG = "MainActivityFragment";

    private Switch mSwitch1;
    private Switch mSwitch2;
    private Switch mSwitch3;

    private boolean mRestoreFlag = false;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView");
        View root = inflater.inflate(R.layout.fragment_main, container, false);

        mSwitch1 = (Switch) root.findViewById(R.id.inc1).findViewById(R.id.switch1);
        mSwitch2 = (Switch) root.findViewById(R.id.inc2).findViewById(R.id.switch1);
        mSwitch3 = (Switch) root.findViewById(R.id.inc3).findViewById(R.id.switch1);


        mSwitch1.setOnCheckedChangeListener(this);
        mSwitch2.setOnCheckedChangeListener(this);
        mSwitch3.setOnCheckedChangeListener(this);
        return root;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Log.d(TAG, "onViewCreated");
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (!mRestoreFlag) {
            return;
        }
        if (buttonView == mSwitch1) {
            Log.d(TAG, "switch1.isChecked()=" + isChecked);
        } else if (buttonView == mSwitch2) {
            Log.d(TAG, "switch2.isChecked()=" + isChecked);
        } else if (buttonView == mSwitch3) {
            Log.d(TAG, "switch3.isChecked()=" + isChecked);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.d(TAG, "onSaveInstanceState");
        outState.putBoolean("switch1", mSwitch1.isChecked());
        outState.putBoolean("switch2", mSwitch2.isChecked());
        outState.putBoolean("switch3", mSwitch3.isChecked());
    }

    @Override
    public void onViewStateRestored(Bundle savedInstanceState) {
        super.onViewStateRestored(savedInstanceState);
        Log.d(TAG, "onViewStateRestored");
        if (savedInstanceState != null) {
            Log.d(TAG, "restore savedInstanceState");
            mSwitch1.setChecked(savedInstanceState.getBoolean("switch1", false));
            mSwitch2.setChecked(savedInstanceState.getBoolean("switch2", false));
            mSwitch3.setChecked(savedInstanceState.getBoolean("switch3", false));
        }
        mRestoreFlag = true;
    }
}