26

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>

そして、これは拡張するクラス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);

}
   }

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

アクティビティ コードでは、onSaveInstanceState を管理せずに、RelativeLayout のみをインフレートします。

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

}

次に、2番目に何かを書いEditTextてデバイスを回転させるとtext、最初の custom の EditText に同じことが表示されますView

なぜこの動作が起こっているのですか?

編集:

android:idを削除し、compound_view.xml でandroid:tagを使用して問題を解決しEditText、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);
}
4

9 に答える 9

10

私はこれを確認していないと言って始めます...しかし、あなたがしていたことと同様に、複合ビューを使用すると同じ問題が発生しました。

問題の根本は、Android がEditTextコントロールの状態を自動的に保存する方法にあると思います。それは "id" によって保存されると思います。したがって、xml に同じ "id" を持つ複数のコントロールがある場合、状態を保存してから状態を復元すると、同じ ID を持つすべてのコントロールが同じ値を取得します。EditTextこれを試すには、通常の xml に2 つのコントロールを追加し、それらに同じandroid:id値を与えて、最終的に同じ値になるかどうかを確認します。

あなたの場合、複合ビューでIDを使用せずに、タグ(View.findViewWithTag)または名前で要素を別の方法で見つけて、それが違いを生むかどうかを確認できます。

私の場合、後者を実行して問題を解決しました。

于 2012-12-17T14:17:11.373 に答える
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);
于 2012-12-17T13:46:20.327 に答える
0

この問題は、From your code のidフィールドが原因で発生しています。クラスの レイアウト ファイルcompound_view.xml
が膨張していることに気付きました。id を作成してファイルに入れると すぐに、Android Studio は自動的にこれらの s をクラス 内の値に1 回だけ作成します。したがって、レイアウト ファイルに時間を 2 回 入れると、 2 つのインスタンスが作成されますが、両方のインスタンスがあり、それぞれのアドレスの場所は 1 つしかありません。したがって、それらはクラスで宣言されている同じアドレスの場所を指しています。compound_viewCompoundView

compound_view.xmlandroid:id="@+id/textLabel"android:id="@+id/textEdit"layout xmlidintR

CompoundViewactivity_main.xmlCompoundViewtextEdittextLabelR


そのため、プログラムでテキストを変更しtextEditたり、テキスト を変更したりするたびに、両方で表示される他のまたはどちらも変更されます。textLabeltextEdittextLabelCompoundView

于 2020-01-09T20:07:01.087 に答える
-1

同じ厄介な問題が発生し、提案されたものとは別の解決策で解決しました。カスタム ビューがインフレートされている場合、ID やタグでそれらを見つけるのではなく、getChildAtメソッドを使用して取得します。インスタンスの状態を保存する必要はありませんでした。

以下に例を示します。

膨らませるカスタム XML (custom_view.xml):

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:textAppearance="?android:attr/textAppearanceMedium"/>
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"/>
</merge>

次に、ビューの初期化中にこの方法でビューを取得します。

private void initView(Context context) {
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    inflater.inflate(R.layout.custom_view, this, true);

    setOrientation(LinearLayout.HORIZONTAL);
    setGravity(Gravity.CENTER);

    TextView mTitleTV = (TextView) getChildAt(0);
    EditText mContentET = (EditText) getChildAt(1);
}

重要: XML からすべての ID を削除する必要があります。

于 2016-02-15T11:45:38.890 に答える