Как сохранить данные EditText при изменении ориентации?

Вопрос:У меня есть экран входа в систему, который состоит из 2 EditTexts для имени пользователя и пароля. Мое требование состоит в том, что при изменении ориентации входные данные (если есть) в EditText должны оставаться такими, как есть, и должен быть также нарисован новый макет. У меня есть 2 макета xml файлов - один в папке

Вопрос:

У меня есть экран входа в систему, который состоит из 2 EditTexts для имени пользователя и пароля. Мое требование состоит в том, что при изменении ориентации входные данные (если есть) в EditText должны оставаться такими, как есть, и должен быть также нарисован новый макет. У меня есть 2 макета xml файлов – один в папке макета и другой в папке макета-земли. Я пытаюсь реализовать следующие два подхода, но ни один из них не идеален:

(1) configChanges: keyboardHidden –. В этом подходе я не предоставляю “ориентацию” в configChanges в файле манифеста. Поэтому я вызываю метод setContentView() как в методах onCreate(), так и onConfigurationChanged(). Он выполняет оба моих требования. Макет изменен, а входные данные в EditTexts также остаются такими, какие есть. Но это имеет большую проблему:

Когда пользователь нажимает кнопку “Вход”, ProgressDialog показывает, что сервер-ответ получен. Теперь, если пользователь поворачивает устройство во время работы ProgressDialog, приложение отключается. Он показывает сообщение об исключении: “Вид не может быть прикреплен к окну”. Я попытался обработать его, используя onSaveInstanceState (который вызывается при изменении ориентации), но приложение все еще сбой.

(2) configChanges: orientation | keyboardHidden – В этом подходе я предоставляю “ориентацию” в манифесте. Итак, теперь у меня есть 2 сценария:

(a) Если я вызываю метод setContentView() как в onCreate(), так и onConfigurationChanged(), макет изменяется соответствующим образом, но данные EditText теряются.

(b) Если я вызываю метод setContentView() в onCreate(), но не в onConfigurationChanged(), то данные EditText не теряются, но макет также не изменяется соответствующим образом.

И в этом подходе, onSaveInstanceState() даже не вызывается.

Таким образом, я нахожусь в очень запугивающей ситуации. Есть ли решение этой проблемы? Пожалуйста помоги. Thanx заранее.

Лучший ответ:

в методе onConfigurationChanged сначала получите данные обоих текстов редактирования в глобальных переменных, а затем вызовите метод setContentView. Теперь снова установите сохраненные данные в тексты редактирования.

Ответ №1

По умолчанию Edittext сохраняет свой экземпляр при изменении ориентации.

Убедитесь, что 2 Edittexts имеют уникальные идентификаторы и имеют одинаковые идентификаторы в обоих макетах.

Таким образом, их состояние должно быть сохранено, и вы можете позволить Android обрабатывать изменение ориентации.

Если вы используете фрагмент, убедитесь, что он имеет уникальный идентификатор, и вы не воссоздаете его при воссоздании Activity.

Ответ №2

Лучший подход – позволить андроиду обрабатывать изменение ориентации. 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()); } Ответ №3

Есть много способов сделать это. Самый простой – 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); } Ответ №4

Im восстанавливая экземпляр для восстановления значений, и он отлично работает для меня:)

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

Следующее должно работать и является стандартным для действий и фрагментов

@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»); } } Ответ №6

Добавление в EditText атрибута

android:id=»@id/anything»

работал со мной.

Ответ №7

Измените атрибут android: configChanges из файла манифеста и позвольте андроиду обрабатывать изменение ориентации, ваши данные в edittext автоматически останутся.

Теперь Проблема, о которой вы упомянули, связана с тем, что действие диалогового окна прогресса закрывается, потому что при изменении ориентации поток, выполняющийся в backgroud, пытается обновить старый компонент диалога, который был виден. Вы можете справиться с этим, закрыв диалоговое окно с помощью метода 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(); } } Ответ №8

Как отмечает Ялла Т, важно не воссоздавать фрагмент. 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(); } Ответ №9

Состояние сохранения = Сохранение (Состояние фрагмента + Состояние активности)

Когда дело доходит до сохранения состояния фрагмента во время изменения ориентации, я обычно так и делаю.

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

Вы можете увидеть полный рабочий код ЗДЕСЬ

Ответ №10

это может помочь вам

если ваш андроид: targetSdkVersion = “12” или меньше

android:configChanges=»orientation|keyboardHidden»>

если ваш андроид: targetSdkVersion = “13” или более

android:configChanges=»orientation|keyboardHidden|screenSize»>

Оцените статью
Добавить комментарий