web-dev-qa-db-ja.com

方向の変更時にEditTextデータを保持する方法は?

ユーザー名とパスワードの2つのEditTextで構成されるログイン画面があります。 私の要件は、方向の変更時に、EditTextの入力データ(ある場合)をそのまま残し、新しいレイアウトも描画することです。 2つのレイアウトxmlファイルがあります-レイアウトフォルダーとその他に1つありますレイアウトランドフォルダー内。次の2つのアプローチを実装しようとしていますが、いずれも完璧ではありません。

(1)configChanges:keyboardHidden-このアプローチでは、マニフェストファイルのconfigChangesに「向き」を指定しません。そのため、onCreate()メソッドとonConfigurationChanged()メソッドの両方でsetContentView()メソッドを呼び出します。それは私の両方の要件を満たします。レイアウトが変更され、EditTextsの入力データもそのまま残ります。しかし、これには大きな問題があります。

ユーザーが[ログイン]ボタンをクリックすると、サーバー応答が受信されるまでProgressDialogが表示されます。 ProgressDialogの実行中にユーザーがデバイスを回転させると、アプリがクラッシュします。 「ビューをウィンドウにアタッチできません」という例外が表示されます。 onSaveInstanceState(向きの変更時に呼び出される)を使用して処理しようとしましたが、アプリはまだクラッシュします。

(2)configChanges:orientation | keyboardHidden-このアプローチでは、マニフェストに「向き」を指定します。だから今、私は2つのシナリオがあります:

(a) onCreate()とonConfigurationChanged()の両方でsetContentView()メソッドを呼び出すと、それに応じてレイアウトが変更されますが、EditTextデータは失われます。

(b) onCreate()でsetContentView()メソッドを呼び出すが、onConfigurationChanged()では呼び出さない場合、EditTextデータは失われませんが、レイアウトもそれに応じて変更されません。

そして、このアプローチでは、onSaveInstanceState()は呼び出されません。

だから私は本当に恐ろしい状況にあります。この問題の解決策はありますか?助けてください。事前に感謝します。

29
Yogesh Somani

onConfigurationChangedメソッドでは、まずグローバル変数の両方の編集テキストのデータを取得してから、setContentViewメソッドを呼び出します。保存したデータを編集テキストに再度設定します。

9
Arpit Raniwala

デフォルトでは、Edittextは向きを変更するときに独自のインスタンスを保存します。

2つのEdittextが一意のIDを持ち、両方のレイアウトで同じIDを持っていることを確認してください。

そうすれば、状態を保存して、Android向きの変更を処理できます。

フラグメントを使用している場合は、フラグメントにも一意のIDが含まれていることを確認し、アクティビティを再作成するときにフラグメントを再作成しないでください。

81
Yalla T.

より良いアプローチは、Androidが方向の変更を処理できるようにすることです。 Androidは正しいフォルダーからレイアウトを自動的に取得し、画面に表示します。あなたがする必要があるのは、編集テキストの入力値を onSaveInsanceState()メソッド これらの保存された値を使用して、編集テキストを初期化します onCreate()メソッド
これを実現する方法は次のとおりです。

@Override
protected void onCreate (Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.login_screen);
    ...
    ...
    String userName, password;
    if(savedInstanceState!=null)
    {
        userName = savedInstanceState.getString("user_name");
        password= savedInstanceState.getString("password");
    }

    if(userName != null)
        userNameEdtTxt.setText(userName);
    if(password != null)
        passEdtTxt.setText(password);
}

>

@Override
    protected void onSaveInstanceState (Bundle outState)
    {
        outState.putString("user_name", userNameEdtTxt.getText().toString());
        outState.putString("password",  passEdtTxt.getText().toString());
    }
33
karn

これを行うには多くの方法があります。最も単純なのは、あなたの質問で2(b)です。マニフェストに_Android:configChanges="orientation|keyboardHidden|screenSize"_と記載してください。そうすれば、アクティビティが向きの変更で破壊されません。

setContentView()onConfigChange()を呼び出します。ただし、setContentView()を呼び出す前に、EditTextデータを文字列に取得し、setContentView()を呼び出した後に元に戻す

_ @Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    mEditTextData = mEditText.getText().tostring();//mEditTextData is a String 
                                                   //member variable
    setContentView(R.layout.myLayout);
    initializeViews();
}

private void initializeViews(){
    mEditText = (EditText)findViewById(R.id.edittext1);
    mEdiText.setText(mEditTextData);
}
_
3
sujith

EditTextに属性を追加する

Android:id="@id/anything"

私に働いた。

3

インスタンスを復元して値を復元すると、私にとってはうまくいきます:)

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.addtask2);
    if(savedInstanceState!=null)
     onRestoreInstanceState(savedInstanceState);

}
2
Aswin Anand

以下は動作するはずで、アクティビティとフラグメントの標準です

@Override
public void onSaveInstanceState (Bundle outState) 
{
     outState.putString("editTextData1", editText1.getText().toString());
     outState.putString("editTextData2", editText2.getText().toString());

     super.onSaveInstanceState(outState);
}

@Override
public void onCreate(Bundle savedInstanceState)
{
      super.onCreate();

      ... find references to editText1, editText2

      if (savedInstanceState != null)
      {
           editText1.setText(savedInstanceState.getString("editTextData1");
           editText2.setText(savedInstanceState.getString("editTextData2");
      }
}
2
chris-tulip

enter image description here

保存状態=保存(フラグメント状態+アクティビティ状態)

向きの変更中にフラグメントの状態を保存することになると、私は通常このようにします。

1)フラグメント状態:

EditText値の保存と復元

// Saving State

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putString("USER_NAME", username.getText().toString());
    outState.putString("PASSWORD", password.getText().toString());
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.user_name_fragment, parent, false);

    username = (EditText) view.findViewById(R.id.username);
    password = (EditText) view.findViewById(R.id.password);


// Retriving value

    if (savedInstanceState != null) {
        username.setText(savedInstanceState.getString("USER_NAME"));
        password.setText(savedInstanceState.getString("PASSWORD"));
    }

    return view;
}

2)アクティビティ状態:

[〜#〜] tag [〜#〜]およびFragmentManager

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

    fragmentManager = getSupportFragmentManager();

    if(savedInstanceState==null) {
        userFragment = UserNameFragment.newInstance();
        fragmentManager.beginTransaction().add(R.id.profile, userFragment, "TAG").commit();
    }
    else {
        userFragment = fragmentManager.findFragmentByTag("TAG");
    }

}

完全に機能するコードを見ることができます [〜#〜] here [〜#〜]

1
Rohit Singh

Yalla Tが指摘したように、フラグメントを再作成しないことが重要です。既存のフラグメントが再利用されても、EditTextはコンテンツを失いません。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // setContentView(R.layout.activity_frame);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    // Display the fragment as the main content.
    // Do not do this. It will recreate the fragment on orientation change!
    // getSupportFragmentManager().beginTransaction().replace(Android.R.id.content, new Fragment_Places()).commit();

    // Instead do this
    String fragTag = "fragUniqueName";
    FragmentManager fm = getSupportFragmentManager();
    Fragment fragment = (Fragment) fm.findFragmentByTag(fragTag);
    if (fragment == null)
        fragment = new Fragment_XXX(); // Here your fragment
    FragmentTransaction ft = fm.beginTransaction();
    // ft.setCustomAnimations(R.xml.anim_slide_in_from_right, R.xml.anim_slide_out_left,
    // R.xml.anim_slide_in_from_left, R.xml.anim_slide_out_right);
    ft.replace(Android.R.id.content, fragment, fragTag);
    // ft.addToBackStack(null); // Depends on what you want to do with your back button
    ft.commit();

}
1

MenifestファイルからAndroid:configChanges属性を削除し、Android edittextのデータが自動的に残る向きの変更を処理します。

さて、あなたが言及した問題は進行方向ダイアログの強制終了です。これは、向きが変更されると、バックグラウンドで実行中のスレッドが表示されていた古いダイアログコンポーネントを更新しようとするためです。 savedinstancestateメソッドのダイアログを閉じて、onRestoreInstanceStateメソッドを実行したいプロセスを呼び出すことで処理できます。

以下はあなたの問題を解決するのに役立つ希望のサンプルです:-

public class MyActivity extends Activity {
    private static final String TAG = "com.example.handledataorientationchange.MainActivity";
    private static ProgressDialog progressDialog;
    private static Thread thread;
    private static boolean isTaskRunnig;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
        setContentView(R.layout.main);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new EditText.OnClickListener() {

            @Override
            public void onClick(View v) {
                perform();
                isTaskRunnig = true;
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    public void perform() {
        Log.d(TAG, "perform");
        progressDialog = Android.app.ProgressDialog.show(this, null,
                "Working, please wait...");
        progressDialog
                .setOnDismissListener(new DialogInterface.OnDismissListener() {

                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        //isTaskRunnig = false;
                    }
                });
        thread = new Thread() {
            public void run() {
                Log.d(TAG, "run");
                int result = 0;
                try {

                    // Thread.sleep(5000);
                    for (int i = 0; i < 20000000; i++) {

                    }
                    result = 1;
                    isTaskRunnig = false;
                } catch (Exception e) {
                    e.printStackTrace();
                    result = 0;
                }
                Message msg = new Message();
                msg.what = result;
                handler.sendMessage(msg);
            };
        };
        thread.start();
    }

    // handler to update the progress dialgo while the background task is in
    // progress
    private static Handler handler = new Handler() {

        public void handleMessage(Message msg) {
            Log.d(TAG, "handleMessage");
            int result = msg.what;
            if (result == 1) {// if the task is completed successfully
                Log.d(TAG, "Task complete");
                try {
                    progressDialog.dismiss();
                } catch (Exception e) {
                    e.printStackTrace();
                    isTaskRunnig = true;
                }

            }

        }
    };

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.d(TAG, "onRestoreInstanceState" + isTaskRunnig);
        if (isTaskRunnig) {
            perform();

        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.d(TAG, "onSaveInstanceState");
        if (thread.isAlive()) {
            thread.interrupt();
            Log.d(TAG, thread.isAlive() + "");
            progressDialog.dismiss();
        }

    }
1
Chandrashekhar