【问题标题】:Android: ListView annoyingly scrolling to top when changing between tabs and backAndroid:在选项卡之间切换和返回时,ListView 烦人地滚动到顶部
【发布时间】:2013-12-19 23:40:56
【问题描述】:

我在附加到 CursorAdapter 的 Fragment 中有一个 ListView。片段有setRetainInstance(true)。在 Fragment 的 onCreate() 方法下,我实例化了 CursorAdapter(将其存储在变量 adapter 中)。然后我在 Fragment 的 onCreateView 方法下调用 listView.setAdapter(adapter)。 CursorAdapter 中的 Cursor 由 CursorLoader 加载。在我的 LoaderCallbacks'onLoadFinished() 中,我调用了adapter.swapCursor(cursor)

总而言之:一切似乎都已到位,因此 ListView 在选项卡之间切换和返回时不应滚动到顶部。但它仍然存在!我会错过什么吗?

这是一些代码。

片段

public class Home extends Fragment{
    ...
    private HomeFeedAdapter adapter; // HomeFeedAdapter extends CursorAdapter
    private AutoQuery autoQuery;     // AutoQuery extends LoaderCallbacks<Cursor>
    ...                              // (See inner class, at the end)

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);

        if(adapter == null)
            adapter = new HomeFeedAdapter(getActivity(), null);
        if(autoQuery == null)
            autoQuery = new AutoQuery();
        getLoaderManager().initLoader(LOADER_INITIAL, null, autoQuery);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        // Layout
        View v = inflater.inflate(R.layout.home, container, false); 
        l = (ListView) v.findViewById(R.id.listview);
        l.setAdapter(adapter);

        return v;
    }

    private class AutoQuery implements LoaderCallbacks<Cursor>{

        @Override
        public Loader<Cursor> onCreateLoader(int id, Bundle args) {

            ...    
            return new CursorLoader(getActivity(), uri,
                    null, null, null, null);
        }

        @Override
        public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
            adapter.swapCursor(cursor);
        }

        @Override
        public void onLoaderReset(Loader<Cursor> loader) {
            adapter.swapCursor(null);
        }

    }

}

活动

public class MainActivity extends SherlockFragmentActivity {

    ...

    private class TabsListener implements ActionBar.TabListener {
        private Fragment fragment;
        private String tag;

        public TabsListener(Fragment fragment, String tag) {
            this.fragment = fragment;
            this.tag = tag; 
        }

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

        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            ft.replace(R.id.fragment_container, fragment, tag);
        }

        @Override
        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
            ft.remove(fragment);
        }

    }

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

        // Layout
        getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        getSupportActionBar().setDisplayHomeAsUpEnabled(false);
        getSupportActionBar().setHomeButtonEnabled(false);
        getSupportActionBar().setDisplayShowTitleEnabled(false);
        setContentView(R.layout.activity_main);

        // Loads fragment
        Fragment fHome, fActivity, fProfile;
        if((fHome = getSupportFragmentManager().findFragmentByTag(HOME)) == null) fHome = new Home();
        if((fActivity = getSupportFragmentManager().findFragmentByTag(ACTIVITY)) == null) fActivity = new FriendsList();
        if((fProfile = getSupportFragmentManager().findFragmentByTag(PROFILE)) == null) fProfile = new Profile();       

        ActionBar.Tab tab;
        tab = getSupportActionBar().newTab();
        tab.setTabListener(new TabsListener(
            fHome,
            HOME
            ));
        getSupportActionBar().addTab(tab, false);

        tab = getSupportActionBar().newTab();
        tab.setTabListener(new TabsListener(
            fActivity,
            ACTIVITY
            ));
        getSupportActionBar().addTab(tab, false);

        tab = getSupportActionBar().newTab();
        tab.setTabListener(new TabsListener(
            fProfile,
            PROFILE
            ));
        getSupportActionBar().addTab(tab, false);

        ...

    }

}

【问题讨论】:

  • 你的活动是什么样的?
  • 我的活动是相当样板。它是SherlockFragmentActivity 的一个实例,并在ActionBar.TabListener 的内部类中创建片段。我将尝试编辑以发布一些活动代码。
  • 我打赌你会创建一个新片段并每次都重新添加它;)它是相关的 :)
  • 已发布。这是一个很好的假设,但实际上我很小心地重新利用了现存的 Fragment 实例。
  • 您正在添加选项卡,如果它不为空,那么您实际上是不是在已经存在的其他片段之上读取它。

标签: android listview android-cursoradapter android-cursorloader


【解决方案1】:

在 Greg Giacovelli 的帮助下,我找到了解决问题的方法。

我将首先声明我不太了解 ListView 位置是如何保存的。每次调用我的 Fragment 的 onCreateView() 时,都会重新创建我的 ListView 实例。例如,当屏幕旋转时会发生这种情况。然而,在屏幕旋转的特定情况下,即使调用了onCreateView() 并因此重新实例化了 ListView,但仍会恢复 ListView 的状态。因此,如果要重新创建 ListView,则必须有其他东西告诉它它以前的位置是什么……我不知道那是什么。我认为这归因于setRetainInstance(true)的机器。

但让我们看看我的主要问题:为什么 ListView 在选项卡更改之间滚动到顶部?正如 Greg 建议的那样,这是因为我使用 replace() 重新添加了 Fragment,因此每次用户翻到另一个选项卡并返回时都会破坏我的 Fragment 并重新创建。

我的解决方案是检查标签是否已添加;如果是,则不添加;否则,添加它。然后,当用户单击选项卡时,我只需分离片段(而不是删除它),然后附加一个新片段。这样,未选中的选项卡的 Fragment 仍然存在,但已分离。

// Tabs listener
private class TabsListener implements ActionBar.TabListener {
    private Fragment fragment;
    private String tag;

    public TabsListener(Fragment fragment, String tag) {
        this.fragment = fragment;
        this.tag = tag; 
    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        if(fragment instanceof ScrollableToTop) ((ScrollableToTop) fragment).scrollToTop();
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        if(!fragment.isAdded()){
            ft.add(R.id.fragment_container, fragment, tag);
        }
        ft.attach(fragment);
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.detach(fragment);
    }

}

【讨论】:

    猜你喜欢
    • 2016-12-23
    • 2015-01-24
    • 2012-08-06
    • 2011-02-22
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 2016-03-13
    相关资源
    最近更新 更多