0

基本上

  • 我有两个布局 activity_main_layout.xml 以及 layout2.xml

  • 我使用getActionbar().newTab()方法在 ActionBar 上创建了两个选项卡

  • 我在activity_main_layout.xml(第一个选项卡)中有一个Button和一个文本框(EditText )

  • 按钮和文本框都有一个动态输入的文本:“Test 123”

  • 选择选项卡 2 时,我有一个代码声明:setContentView(R.layout.layout2)以便它显示第二个布局,并且选项卡 1 类似:setContentView(R.layout.activity_main)

    重新选择选项卡 1 时,动态输入的文本“Test 123”消失了,我只剩下在 XML 中设计时设置的文本。因此,我目前被迫在选择选项卡之前保存 Buttons 和 EditTexts 的内容,并在选择选项卡后恢复它们。

我认为这不是正确的做法。我已经在使用onSaveInstanceState()onRestoreInstanceState()以及savedInstanceState.putXX 和 getXX等来在屏幕旋转时保存内容,但它似乎不适用于当前问题。到目前为止,我一直无法找到答案。请问有人有什么线索吗?任何回应将不胜感激。

4

4 回答 4

0

除了“向大师学习”状态之外,还有更好的方法来构建这个结构(页面适配器/页面查看器/片段......)它应该仍然可以正确使用您的 Bundle saveInstanceState 正常工作。

你可以发布你的代码吗?

看到代码后编辑:

您可能需要在 onCreate() 中检查您的 Bundle savedInstanceState。这看起来有点像

    @Override
    public void onCreate(Bundle savedInstanceState) {
         [...]
     if(savedInstanceState != null){
       //restore your stuff from the Bundle
      }else{
       // there is nothing to restore, so (down)load your data.
       }
    }

您可以在https://stackoverflow.com/a/6722854/1868384附近找到一个很好的详细解释

于 2012-12-30T14:04:20.410 回答
0

这是我的代码:

活动主.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >

<Button
    android:id="@+id/btn_One"
    android:layout_width="100dp"
    android:layout_height="wrap_content"
    android:layout_weight="1.70"
    android:text="Activity_main.xml - Design Time Text"
    android:textSize="12sp"
    android:onClick="btnOne_OnClick"
    android:textStyle="normal" />

布局2.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >

            <Button
                android:id="@+id/btn_Two"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Layout2.xml - Design Time Text"
                android:textSize="12sp"
                android:textStyle="normal" />

在主代码中,请注意注释:

public class MainActivity extends Activity implements ActionBar.TabListener {

ActionBar.Tab Tab_1 = null, Tab_2 = null;
Button btn_One = null, btnTwo = null;

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ///////////////////////////////////////////////////////////////////
    ActionBar actionbar = (ActionBar) getActionBar();
    actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    Tab_1 = actionbar.newTab().setText("Tab 1");
    Tab_2 = actionbar.newTab().setText("Tab 2");

    Tab_1.setTag(1);
    Tab_2.setTag(2);


    Tab_1.setTabListener(this);
    Tab_2.setTabListener(this);        

    actionbar.addTab(Tab_1);
    actionbar.addTab(Tab_2);
    ///////////////////////////////////////////////////////////////////

    btn_One = (Button)this.findViewById(R.id.btn_One);
}


public void btnOne_OnClick(View v) {
    ((Button)v).setText("Clicked");
    btn_One = ((Button)v);
}

@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {}

// Here is what the problem is:
// After you click btn_one, the text changes to "Clicked" - good! - however
// after Tab 1 gets reselected, the text off btn_One (btn_One) gets reset back to the one
// set in design time: "Activity_main.xml - Design Time Text", so the "Clicked" text disappears
// The interesting thing is, when you rotate the screen, the text gets re-initialized to "Clicked" and that's
// because of onRestoreInstanceState(). So it looks like when a tab gets reselected, the design time screen
// gets re-drawn and onRestoreInstanceState doesn't get recalled.
// My "workaround" for the above issue would be to create a global 
// "Bundle" poiner and pass the address of the one from onSaveInstanceState(Bundle savedInstanceState)
// to the global Bundle pointer and then call onRestoreInstanceState(*the_global_bundle_pointer*) 
// when a tab gets reselected so that it restores the state.

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {

    int selectedTab = (Integer) tab.getTag();

    if (selectedTab == 1) this.setContentView(R.layout.activity_main);
    if (selectedTab == 2) this.setContentView(R.layout.layout2);

}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {}

@Override
public void onSaveInstanceState(Bundle savedInstanceState) 
{
  if (btn_One != null) savedInstanceState.putString("btn_One", btn_One.getText().toString());

  super.onSaveInstanceState(savedInstanceState);  
}  

// When the instance is restored, reload all data
@Override  
public void onRestoreInstanceState(Bundle savedInstanceState) 
{  
    super.onRestoreInstanceState(savedInstanceState);

    if (btn_One != null) btn_One.setText(savedInstanceState.getString("btn_One").toString());  
}       

}

另外,我说两个选项卡的原因是我可以以最简单的方式演示问题,以便人们可以理解我要解决的问题。我的真实项目使用了两个以上的选项卡。

对于上述问题,我的“解决方法”是创建一个全局“Bundle”指针,并将该指针的地址从onSaveInstanceState(Bundle savedInstanceState)传递给全局 Bundle 指针,然后在重新选择选项卡时调用onRestoreInstanceState (*the_global_bundle_pointer*)使其恢复状态。

你怎么看?

于 2012-12-30T21:49:02.703 回答
0

谢谢你们俩。事实证明,对于 Android,一旦将新的内容布局设置为 Activity,现有的 UI 元素(如文本框、先前布局的按钮等)将不再可用,因此尝试访问它们将导致访问冲突。设置内容布局后,UI 元素似乎是从头开始重建的,因此会丢失所有数据。嗯,这就是我个人注意到的,而且这似乎是一种默认行为。我不知道这种行为是否可以改变。

我制作了自己的“自定义解决方案”。我所做的只是创建一个新类,其中包含一堆数据成员。每次我为 Activity 设置新内容时,例如当我在单击选项卡或旋转设备 (onSaveInstance) 时应用布局时,我会保存/恢复此类中的值。我曾经使用过 Bundle putInt、putString、putParcelable 等,但我决定采用不同的方法。以我的方式,我处于控制之中,并且我确切地知道代码发生了什么。

于 2013-01-01T07:51:41.833 回答
0

如果您只有 2 个选项卡,为什么不使用页面适配器?在您更改手机位置或退出应用程序之前,您不会丢失任何信息。

基本上是这样的(我把我的一个代码给你了)。

注意:我使用数据包 ShelockActivity 为 android > 2.0 设置 tabsmenu

主类

public class MainClass extends SherlockActivity implements ActionBar.TabListener {
ViewPager myPager;
AdapterClass adapter;
Context con = null;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    con = this.getBaseContext();
    //Restore info in case flip mobile      
    final Myobject data = (Myobject) getLastNonConfigurationInstance();     
    Bundle extras = getIntent().getExtras(); 

   //Tab bar
    getSupportActionBar().setDisplayShowHomeEnabled(false);
    getSupportActionBar().setDisplayShowTitleEnabled(false);
    getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    //loop for add more
    ActionBar.Tab tab = getSupportActionBar().newTab();
    tab.setText("text tab");

            if (data != null) {
            getdatatoyourobject(data);
        }
    myPager = (ViewPager) findViewById(R.id.panelpager);    
    myPager.setAdapter(adapter);    
    myPager.setOnPageChangeListener(new OnPageChangeListener() {
          @Override
          public void onPageSelected(int index) {
              getSupportActionBar().setSelectedNavigationItem(index);            
          }
    adapter = new AdapterClass(Parameters for your adapterclass);


        @Override
        public void onPageScrollStateChanged(int arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
            // TODO Auto-generated method stub

        }

    });
}
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
    // TODO Auto-generated method stub
        myPager.setCurrentItem(tab.getPosition(),true);         
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    // TODO Auto-generated method stub

}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
    // TODO Auto-generated method stub

}
@Override
public Object onRetainNonConfigurationInstance() {
    final Myobject a = new Myobject();
    return a;       
}

public class Myobject {
    Type variable = adapter.variable; //do for all variables to restore     
}

public void getdatatoyourobject(Myobject a){
    adapter.variable = a.variable;    //do for all variables to restore     
}
}

适配器类

  public class Adapterclass extends PagerAdapter {

  public int getCount() {
      return 2; //NUMBER OF PAGES
  }  

  public Adapterclass () {      
  }  

 public View view = null; //create rest of variables to restore as public

 public Object instantiateItem(View collection, int position) {

  LayoutInflater inflater = (LayoutInflater) collection.getContext()
          .getSystemService(Context.LAYOUT_INFLATER_SERVICE);


  switch (position) {
  case 0:
      view = inflater.inflate(R.layout.page1, null);
       //bla bla bla
       break;
//do more cases (pages)
  }
      ((ViewPager) collection).addView(view, 0);

     return view;
 }

 @Override
 public void destroyItem(View arg0, int arg1, Object arg2) {
      ((ViewPager) arg0).removeView((View) arg2);

  }

  @Override
  public boolean isViewFromObject(View arg0, Object arg1) {
      return arg0 == ((View) arg1);

  }

  @Override
  public Parcelable saveState() {
      return null;
  }
}

主.XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

<android.support.v4.view.ViewPager
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/panelpager"/>

于 2012-12-30T13:38:09.413 回答