带有scrollview的Android操作栏选项卡在方向更改后进行了重复查看

时间:2012-01-16 20:00:33

标签: android screen-orientation android-actionbar

我有一个非常简单的代码,我使用带有标签片段的Action Bar。它在加载后工作正常,但在方向改变后它变得疯狂。旧片段也可见(为什么?)。

对不起图像上的匈牙利文字,但我希望没关系。 After orientation change

我附上代码,也许有助于解决这个问题。

主要活动:

public class Main extends Activity
{
    private static ActionBar actionBar;

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

        // setup action bar for tabs
        actionBar = getActionBar();
        actionBar.removeAllTabs();
        if (actionBar.getTabCount() == 0)
        {
            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

            Tab tab = actionBar.newTab().setText(R.string.starter).setTabListener(new TabListener<Starter>(this, "starter", Starter.class));
            actionBar.addTab(tab);

            tab = actionBar.newTab().setText(R.string.newword).setTabListener(new TabListener<NewWord>(this, "newwod", NewWord.class));
            actionBar.addTab(tab);

            tab = actionBar.newTab().setText(R.string.feedback).setTabListener(new TabListener<Feedback>(this, "feedback", Feedback.class));
            actionBar.addTab(tab);
        }

        if (savedInstanceState != null)
        {
            actionBar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState)
    {
        super.onSaveInstanceState(outState);
        outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
    }
}

TabListener(与Google示例相同):

public class TabListener<T extends Fragment> implements android.app.ActionBar.TabListener
{
    private Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    /**
     * Constructor used each time a new tab is created.
     * 
     * @param activity
     *            The host Activity, used to instantiate the fragment
     * @param tag
     *            The identifier tag for the fragment
     * @param clz
     *            The fragment's Class, used to instantiate the fragment
     */
    public TabListener(Activity activity, String tag, Class<T> clz)
    {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft)
    {
        // User selected the already selected tab. Usually do nothing.

    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft)
    {
        // Check if the fragment is already initialized
        if (mFragment == null)
        {
            // If not, instantiate and add it to the activity
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);
        } else
        {
            // If it exists, simply attach it in order to show it
            ft.attach(mFragment);
        }

    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft)
    {
        if (mFragment != null)
        {
            // Detach the fragment, because another one is being attached
            ft.detach(mFragment);
        }
    }

}

片段:

public class Starter extends Fragment
{
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        setRetainInstance(false);
        return inflater.inflate(R.layout.newword, container, false);
    }
}

和布局XML:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="5dp" >

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:text="@string/newword"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <EditText
            android:id="@+id/newwordtext"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/wordhint" />

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:text="@string/description"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textStyle="bold" />

        <EditText
            android:id="@+id/descriptionwordtext"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/descriptionhint"
            android:inputType="textMultiLine"
            android:minLines="4" />

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:text="@string/origin"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textStyle="bold" />

        <EditText
            android:id="@+id/origintext"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/originhint" />

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:text="@string/source"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textStyle="bold" />

        <EditText
            android:id="@+id/sourcetext"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/sourcehint" />

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:text="@string/name"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textStyle="bold" />

        <EditText
            android:id="@+id/nametext"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:inputType="textPersonName" />

        <Button
            android:id="@+id/sendbutton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:text="@string/send" />
    </LinearLayout>

</ScrollView>

提前谢谢你!

5 个答案:

答案 0 :(得分:5)

我在其他question找到了可用的答案。

我需要修改我的TabListener(我把它作为内部类移动到我的Main活动类中):

private class TabListener<T extends Fragment> implements android.app.ActionBar.TabListener
    {
        private Fragment mFragment;
        private final Activity mActivity;
        private final String mTag;
        private final Class<T> mClass;

        /**
         * Constructor used each time a new tab is created.
         * 
         * @param activity
         *            The host Activity, used to instantiate the fragment
         * @param tag
         *            The identifier tag for the fragment
         * @param clz
         *            The fragment's Class, used to instantiate the fragment
         */
        public TabListener(final Activity activity, final String tag, final Class<T> clz)
        {
            mActivity = activity;
            mTag = tag;
            mClass = clz;
        }

        @Override
        public void onTabReselected(final Tab tab, final FragmentTransaction ft)
        {
            // User selected the already selected tab. Usually do nothing.
        }

        @Override
        public void onTabSelected(final Tab tab, final FragmentTransaction ft)
        {
            mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
            if (mFragment == null)
            {
                mFragment = Fragment.instantiate(mActivity, mClass.getName());
                ft.add(android.R.id.content, mFragment, mTag);
            }
            else
            {
                ft.attach(mFragment);
            }
        }

        @Override
        public void onTabUnselected(final Tab tab, final FragmentTransaction ft)
        {
            if (mFragment != null)
            {
                ft.detach(mFragment);
            }
        }
    }

所以在我添加片段(再次)之前,我检查它是否存在(并获得它的参考),如果它存在,我只附加它。

答案 1 :(得分:2)

尝试使用ft.replace(R.id.content,mFragment)代替ft.attach(mFragment);在onTabSelected函数

答案 2 :(得分:1)

我找到了一个非常简单的解决方案来避免碎片重复:

    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
        Fragment currentFragment = getFragmentManager().findFragmentByTag(CURRENT_FRAGMENT_TAG);
        if (currentFragment == null || !currentFragment.getClass().equals(mFragment.getClass())) {
            ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
            ft.add(android.R.id.content, mFragment, CURRENT_FRAGMENT_TAG);
        }
    }

    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
        ft.remove(mFragment);
    }

解决方案的关键在于:

currentFragment == null || !currentFragment.getClass().equals(mFragment.getClass())

仅当片段的类别不同时,此条件才有效。如果你有相同类的不同实例,你必须在片段中放置一个额外的属性来识别他的函数(或与条件的关联和生成条件!currentFragment.getClass()。equals(mFragment.getClass())true :例如,您可以使用FragmentTransaction标记功能。

再见 亚历克斯。

答案 3 :(得分:0)

public void onTabSelected(Tab tab, FragmentTransaction ft)
    {
        // Check if the fragment is already initialized
        if (mFragment == null)
        {
            if(ft.findFragmentById(android.R.id.content) == null){
            // If not, instantiate and add it to the activity
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);
            }
        } else
        {
            // If it exists, simply attach it in order to show it
            ft.attach(mFragment);
        }

    }

类似的东西,因为你的问题是你添加了两次相同的片段,我们只需找到...

答案 4 :(得分:0)

我通过在标签监听器构造函数中查找片段来解决这个问题。

public class TabListener<T extends Fragment> implements ActionBar.TabListener 
{
    private Fragment fragment;
    private final SherlockFragmentActivity activity;
    private final String tag;
    private final Class<T> clazz;

    public TabListener(SherlockFragmentActivity activity, String tag, Class<T> clazz) 
    {
        this.activity = activity;
        this.tag = tag;
        this.clazz = clazz;

        FragmentManager manager = ((SherlockFragmentActivity) activity).getSupportFragmentManager();
        fragment = manager.findFragmentByTag(tag);
    }
...
}