[英]Restore views in a fragment added programmatically
我有一個帶有導航抽屜的活動(Eclipse新應用程序向導提供的基本活動)。 我有一個FrameLayout作為應用程序不同片段的容器,當在導航抽屜中選擇一個項目時,這些片段將被替換。 它們也被添加到BackStack。
這些片段包含一個LinearLayout,其中包含一些EditTexts和一個Button。 如果按下該按鈕,則將創建一個新的LinearLayout,並將兩個TextViews與EditTexts的內容一起添加到其中。 用戶可以多次重復此選項,因此我無法確定需要多少LinearLayouts,因此需要以編程方式添加它們。
這些xml片段之一:
<LinearLayout
android:id="@+id/pen_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/new_pen_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:background="@drawable/border"
android:orientation="vertical"
android:paddingBottom="@dimen/home_section_margin_bottom"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/home_section_margin_top" >
<EditText
android:id="@+id/new_pen_round"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:hint="@string/new_pen_round_hint"
android:textSize="@dimen/normal_text_size" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2" >
<Button
android:id="@+id/new_pen_cancel_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/new_item_button_margin_right"
android:layout_weight="1"
android:background="@drawable/button_bg"
android:paddingBottom="@dimen/new_item_button_padding_bottom"
android:paddingTop="@dimen/new_item_button_padding_top"
android:text="@string/new_item_cancel_button"
android:textSize="@dimen/normal_text_size" />
<Button
android:id="@+id/new_pen_insert_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/new_item_button_margin_left"
android:layout_weight="1"
android:background="@drawable/button_bg"
android:paddingBottom="@dimen/new_item_button_padding_bottom"
android:paddingTop="@dimen/new_item_button_padding_top"
android:text="@string/new_pen_insert_button"
android:textSize="@dimen/normal_text_size" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
實際上還有許多其他EditText,但是為了簡短起見,我在這里刪除了它們,結果是一樣的。 它是java文件:
public class PenaltiesFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_penalties, container, false);
Button insertNewPen = (Button) view.findViewById(R.id.new_pen_insert_button);
insertNewPen.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
TextView round = (TextView) getActivity().findViewById(R.id.new_pen_round);
LinearLayout layout = (LinearLayout) getActivity().findViewById(R.id.pen_layout);
int numChilds = layout.getChildCount();
CustomPenaltyLayout penalty = new CustomPenaltyLayout(getActivity(), round.getText());
layout.addView(penalty, numChilds - 1);
}
});
return view;
}
}
我刪除了一些無用的方法,它們只是默認方法。 CustomPenaltyLayout
是我創建的LinearLayout的子類,它只是創建一些TextViews並將其添加到自身。
這里一切都很好。 用戶在EditText中插入數據,按下Insert按鈕,將創建新的布局並將其添加到片段中。
我要實現的目標是:假設我打開導航抽屜並選擇另一頁,該片段將被替換,如果我返回該片段(通過導航抽屜或通過“后退”按鈕),我想要用戶添加的文本,仍然在那里。
我不會每次切換回該片段時都調用PenaltiesFragment.newInstance()
,而是創建一次PenaltiesFragment
對象並繼續使用該對象。 這是我的工作:
Fragment fragment;
switch (newContent) {
// various cases
case PEN:
if(penFragment == null) // penFragment is a private field of the Main Activity
penFragment = PenaltiesFragment.newInstance();
fragment = penFragment;
break;
}
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, fragment)
.addToBackStack("fragment back")
.commit();
我知道片段重新加載時會再次調用onCreateView()
,對嗎? 因此,這可能就是為什么我看到一個新的空白片段。 但是,如何找回插入的CustomPenaltyLayout
? 我無法在onCreateView()
方法中創建它。
我找到了解決問題的方法。 我用ViewPager替換了Android自動創建的默認FrameLayout作為片段的容器,然后創建了一個FragmentPagerAdapter,如下所示:
public static class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
Fragment fragment;
switch (position) {
// ...other cases
case PEN:
fragment = PenaltiesFragment.newInstance();
break;
// ...other cases
}
return fragment;
}
@Override
public int getCount() {
return 6;
}
}
然后,要始終保持所有視圖的唯一要做的事情就是將此行添加到我的活動onCreate
方法中。
mPager.setOffscreenPageLimit(5);
有關此方法如何工作的詳細信息,請參見文檔 。
盡管這樣,我不得不重新實現所有后退按鈕邏輯,但這仍然很簡單,這就是我的方法:我創建了一個java.util.Stack<Integer>
對象,向其中添加片段編號(除非您使用后退按鈕,請參見下文),並在我的歷史記錄堆棧不為空時覆蓋onBackPressed()
以使其彈出最后查看的片段,而不是使用后退堆棧。
您要避免在按下“后退”按鈕時將元素推入堆棧,否則如果您繼續使用“后退”按鈕而不是最終退出,則會陷入兩個片段之間。
我的代碼:
MyAdapter mAdapter;
ViewPager mPager;
Stack<Integer> pageHistory;
int currentPage;
boolean saveToHistory;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.container);
mPager.setAdapter(mAdapter);
mPager.setOffscreenPageLimit(5);
pageHistory = new Stack<Integer>();
mPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
if(saveToHistory)
pageHistory.push(Integer.valueOf(currentPage));
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
saveToHistory = true;
}
@Override
public void onBackPressed() {
if(pageHistory.empty())
super.onBackPressed();
else {
saveToHistory = false;
mPager.setCurrentItem(pageHistory.pop().intValue());
saveToHistory = true;
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.