首页 文章

使用支持库实现TabListener

提问于
浏览
20

我正在尝试实现Tab Navigation,但我想确保拥有旧版Android的人仍然可以使用我的应用程序 .

应用程序考虑到ATM非常简单,我只是想了解如何实现布局,然后我将添加缺少的位 .

无论如何,我有一个扩展 Fragment Activity 的容器活动(以确保兼容性),并且此活动使用 ActionBar 创建一个TabView(我相信我的问题存在于此处) . 该应用程序将尝试创建三个选项卡并将其添加到ActionBar,我想确保用户可以使用横向导航来回滚动 .

这是TabListener我试图实现:

public static class TabListener<T extends Fragment> implements ActionBar.TabListener {

    private Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    public TabListener(Activity activity, String tag, Class<T> clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

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

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

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

这是我的导入,因为我想确保我使用的是支持库:

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.view.Menu;

但是,Eclipse给出了 TabListener 方法的问题 . 它告诉我以下内容:"The type LayoutContainer.TabListener must implement the inherited abstract method ActionBar.TabListener.onTabSelected(ActionBar.Tab, FragmentTransaction)"

当我选择 Add unimplemented methods 时,Eclipse基本上会添加 OnTabSelected OnTabReselectedOnTabUnselected 方法,但这一次,将Fragment( android..app.Fragment )的非支持版本作为参数传递 .

有关如何通过支持库进行另一个横向导航实现以确保兼容性的任何想法?

5 回答

  • 0
    actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    
    actionBar.setDisplayShowHomeEnabled(false);
    actionBar.setDisplayShowTitleEnabled(false);
    
    tabA = actionBar.newTab().setText("");
    tabB = actionBar.newTab().setText("");
    
    Fragment fragmentA = new AFragmentTab();
    Fragment fragmentB = new BFragmentTab();
    
    tabA.setTabListener(new MyTabsListener(fragmentA));
    tabB.setTabListener(new MyTabsListener(fragmentB));
    
    actionBar.addTab(tabA);
    actionBar.addTab(tabB);
    

    标签监听器如下:

    protected class MyTabsListener implements ActionBar.TabListener{
        private Fragment fragment;
    
        public MyTabsListener(Fragment fragment){
            this.fragment = fragment;
        }
        public void onTabSelected(Tab tab, FragmentTransaction ft){
            ft.add(R.id.layout2, fragment, null);
        }
        public void onTabReselected(Tab tab, FragmentTransaction ft) {
        }
        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
            ft.remove(fragment);
        }
    }
    

    然后你为每个标签创建一个类:

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

    但请记住,3.0以下的Android版本不支持操作栏 . 如果你想在旧版本中使用它,我建议你使用actionBarSherlock Library .

  • 33

    嗯 . 而Malek的作品并没有直接回答这个问题 .

    您可以简单地忽略回调中获得的片段事务并使用您自己的片段事务:

    android.support.v4.app.FragmentTransaction fft = mActivity.getSupportFragmentManager().beginTransaction();
    

    只需确保您的活动是FragmentActivity,您就可以开始新的片段事务 .

    另外,fragmentTransaction中的replace()方法比add()和remove()方便得多 .

  • 3

    关键是要使用

    import android.support.v7.app.ActionBar;
    

    ... 而不是 ...

    import android.app.ActionBar;
    

    这避免了Nelson Ramirez发布的聪明的解决方法 .

    基于the official documentation的以下完整示例已经过测试,可以在Android 3.0,API 11中运行

    package com.example.myapp;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentTransaction;
    import android.support.v7.app.ActionBar;
    import android.support.v7.app.ActionBarActivity;
    import android.view.*;
    import android.widget.TextView;
    
    public class NavigationTabsBasicDemoActivity extends ActionBarActivity {
    
        static public class TabListener<T extends Fragment> implements 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 pClass   The fragment's Class, used to instantiate the
             *                 fragment
             * @see <a
             * href="http://developer.android.com/guide/topics/ui/actionbar
             * .html#Tabs">
             * Developers Guide > Action Bar > Adding Navigation Tabs</a>
             */
            public TabListener(Activity activity, String tag, Class<T> pClass) {
                mActivity = activity;
                mTag = tag;
                mClass = pClass;
            }
    
            @Override
            public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
                if (mFragment == null) {
                    mFragment = Fragment.instantiate(mActivity, mClass.getName());
                    ft.add(android.R.id.content, mFragment, mTag);
                } else {
                    // If it exists, attach it in order to show it
                    ft.attach(mFragment);
                }
            }
    
            @Override
            public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
                if (mFragment != null) {
                    // Detach the fragment, because another one is about to be
                    // attached.
                    ft.detach(mFragment);
                }
            }
    
            @Override
            public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
                // Do nothing.
            }
        }
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // No need for setContentView() to be used, Instead  we use the root
            // android.R.id.content as the container for each fragment,
            // which is set in the TabListener
    
            ActionBar actionBar = getSupportActionBar();
            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
            actionBar.setDisplayShowTitleEnabled(true);
    
            ActionBar.Tab tab = actionBar.newTab().setText("Artist").setTabListener(
                    new TabListener<PlaceholderFragment>(this,
                                                         "artist",
                                                         PlaceholderFragment
                                                                 .class));
            actionBar.addTab(tab);
    
            tab = actionBar.newTab().setText("Album").setTabListener(
                    new TabListener<PlaceholderFragment>(
                        this,
                        "album",
                        PlaceholderFragment.class));
            actionBar.addTab(tab);
        }
    
        /**
         * In this example use one Fragment but display different data based on
         * which
         * tab is shown. In production you'd probably use a separate fragment.
         */
        public static class PlaceholderFragment extends Fragment {
    
            public PlaceholderFragment() {
            }
    
            @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                     Bundle savedInstanceState) {
                View rootView = inflater.inflate(
                        R.layout.fragment_navigation_tabs_basic_demo,
                                                 container,
                                                 false);
                TextView outputTextView = (TextView) rootView.findViewById(
                                            R.id.output_textView);
                outputTextView.setText("Hello " + getTag());
                return rootView;
            }
        }
    }
    
  • 0

    我想实现@nelson-ramirez,但访问mActivity时出错,所以这是这两个答案的组合,适用于我的项目,它使用带有Facebook登录的标签导航(需要support.v4库) . 键是,创建一个私有的mActivity,然后在启动监听器时传入并分配,并创建自己的Fragment Transaction,而不是使用参数中的那个 . 此外,使用v4库将主活动更改为FragmentActivity,这允许访问getSupportFragmentManager() .

    public class MyTabListener implements ActionBar.TabListener{
        private Fragment fragment;
        private FragmentActivity mActivity;
    
        public MyTabListener(Fragment fragment, FragmentActivity activity){
            this.fragment = fragment;
            this.mActivity = activity;
        }
    
        @Override
        public void onTabSelected(ActionBar.Tab tab, android.app.FragmentTransaction ft) {
            android.support.v4.app.FragmentTransaction fft = mActivity.getSupportFragmentManager().beginTransaction();
            fft.replace(R.id.fragment_container, fragment);
            fft.commit();
        }
    
        @Override
        public void onTabUnselected(ActionBar.Tab tab, android.app.FragmentTransaction ft) {
            android.support.v4.app.FragmentTransaction fft = mActivity.getSupportFragmentManager().beginTransaction();
            fft.remove(fragment);
        }
    
        @Override
        public void onTabReselected(ActionBar.Tab tab, android.app.FragmentTransaction ft) {
    
        }
    }
    
  • 5

    关于如何通过支持库进行另一种横向导航实现以确保兼容性的任何想法?

    替代解决方案

    截至2015年5月29日,您可以使用Android Design Support Library . 它包含Tab Layout并支持Android 2.1或更高版本的设备 .

相关问题