为什么自定义复合视图中的EditText会重复使用在另一个复合视图实例中输入的文本?

moo*_*oid 18 android android-custom-view android-edittext android-view

我正在尝试编写由a TextViewEditText_compound_view.xml_ 组成的自定义复合视图:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/compoundText"
android:layout_width="match_parent"
android:layout_height="wrap_content" >

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

<EditText
    android:id="@+id/textEdit"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="enter text here" >
</EditText>
Run Code Online (Sandbox Code Playgroud)

这是扩展的类LinearLayout:

public class CompoundView extends LinearLayout {

public CompoundView(Context context, AttributeSet attrs) {
    super(context, attrs);

    readAttributes(context, attrs);
    init(context);
}

public CompoundView(Context context) {
    super(context);

    init(context);
}

private void init(Context c) {

    final LayoutInflater inflater = (LayoutInflater) c
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    inflater.inflate(R.layout.compound_view, this);

}
   }
Run Code Online (Sandbox Code Playgroud)

现在,如果我View在_activity_main.xml_中使用其中的2 个:

<RelativeLayout 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"
tools:context=".MainActivity" >
<it.moondroid.compoundview.example.CompoundView
    android:id="@+id/compoundview1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true" />

<it.moondroid.compoundview.example.CompoundView
    android:id="@+id/compoundview2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/compoundview1" />
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

并且在活动代码中我只膨胀RelativeLayout,而不管理onSaveInstanceState:

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

}
Run Code Online (Sandbox Code Playgroud)

然后当我在第二个中写东西EditText并旋转我的设备时,text第一个自定义的EditText中出现相同的内容View.

为什么会发生这种行为?

编辑:

我通过删除解决问题ID:安卓和使用安卓标签EditText在compound_view.xml,然后在管理类CompoundView的EditText上状态的保留:

@Override
protected Parcelable onSaveInstanceState() {

    Bundle bundle = new Bundle();
    bundle.putParcelable("instanceState", super.onSaveInstanceState());
    bundle.putString("currentEdit", mEditText.getText().toString());
    bundle.putBoolean("isFocused", mEditText.hasFocus());
    return bundle;

}

@Override
protected void onRestoreInstanceState(Parcelable state) {

    if (state instanceof Bundle) {
        Bundle bundle = (Bundle) state;
        mEditText.setText(bundle.getString("currentEdit"));
        if (bundle.getBoolean("isFocused")) {
            mEditText.requestFocus();
        }
        super.onRestoreInstanceState(bundle.getParcelable("instanceState"));
        return;
    }

    super.onRestoreInstanceState(state);
}
Run Code Online (Sandbox Code Playgroud)

Dha*_*dra 14

您需要使用禁用EditText 的SaveEnabled属性android:saveEnabled="false"

在您的自定义视图中,您正在从定义了 ID 的 XML 膨胀布局。如果视图定义了 ID,Android 操作系统具有保存和恢复视图状态的默认功能。

这意味着它会在 Activity 暂停时保存 EditText 的文本,并在 Activity 恢复时自动恢复。在您的情况下,您多次使用此自定义视图并且膨胀相同的布局,因此您的所有 EditText 都具有相同的 ID。现在,当 Activity 暂停时,Android 将检索 EditText 的值并根据其 ID 进行保存,但由于每个 EditText 具有相同的 ID,因此值将被覆盖,因此它将在您的所有 EditText 中恢复相同的值。


stu*_*ess 10

我首先要说的是我没有证实这一点......但是在使用复合视图时我遇到了同样的问题,类似于你正在做的事情.

我认为问题的根源是Android如何自动保存EditText控件的状态,我认为它通过"id"保存它.因此,如果xml中有多个具有相同"id"的控件,那么当它保存状态,然后恢复状态时,具有相同id的所有控件都会获得相同的值.您可以通过向EditText普通xml 添加2个contol来尝试此操作,并为它们提供相同的android:id值,并查看它们是否最终获得相同的值.

在您的情况下,您可以尝试不在复合视图中使用id,而是通过tag(View.findViewWithTag)或名称以另一种方式查找元素,并查看是否有所不同.

就我而言,我通过做后者来解决问题.

  • 谢谢!删除id已解决了问题; 但是我必须在自定义视图中管理EditText状态的保存 (2认同)

Aba*_*ano 0

看看我在你的问题中的评论,并确保你正确地引用了你的观点。

我正在使用你的代码,如下所示:

CompoundView cv1 = (CompoundView) findViewById(R.id.compoundview1);
TextView tv1 = (TextView) cv1.findViewById(R.id.textEdit);

CompoundView cv2 = (CompoundView) findViewById(R.id.compoundview2);
TextView tv2 = (TextView) cv2.findViewById(R.id.textEdit);
Run Code Online (Sandbox Code Playgroud)