还原以编程方式添加的片段中的视图

时间:2014-09-24 13:54:34

标签: java android android-layout android-fragments

我有一个带导航抽屉的活动(Eclipse新应用程序向导提供的基本活动)。我有一个FrameLayout作为应用程序的不同片段的容器,在导航抽屉中选择项目时会替换它们。它们也被添加到BackStack中。

这些片段包含一个LinearLayout,它有一些EditTexts和一个Button。如果按下该按钮,则会创建一个新的LinearLayout,并使用EditTexts的内容向其中添加几个TextView。用户可以多次重复此选项,因此我无法确定我需要多少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>

实际上还有很多其他的EditTexts,但我在这里删除它们以保持简短,结果是一样的。这是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的子类,它只是创建一些TextView并将它们添加到自身。

这里一切正常。用户在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()方法中创建它。

1 个答案:

答案 0 :(得分:0)

我找到了解决问题的方法。我使用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);

有关此方法如何工作的详细信息,请参阅documentation

但是,这种方式,我不得不重新实现所有后退按钮逻辑,但它仍然很简单,这就是我做的方式:我创建一个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;
    }
};