【问题标题】:Implementing a TabListener using the Support Library使用支持库实现 TabListener
【发布时间】:2012-10-04 07:05:46
【问题描述】:

我正在尝试实现选项卡导航,但我想确保拥有旧版本 Android 的用户仍然可以使用我的应用程序。

ATM 中的应用程序相当简单,我只是想了解如何实现布局,然后我将添加缺失的部分。

无论如何,我有一个扩展 Fragment Activity(以确保兼容性)的容器 Activity,并且此 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 方法的问题。它告诉我以下内容:“LayoutContainer.TabListener 类型必须实现继承的抽象方法 ActionBar.TabListener.onTabSelected(ActionBar.Tab, FragmentTransaction)”

当我选择 Add unimplemented methods 时,Eclipse 基本上添加了 OnTabSelected OnTabReselectedOnTabUnselected 方法,但是这一次,通过了不支持的版本Fragment (android..app.Fragment) 作为参数。

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

【问题讨论】:

    标签: android android-fragments android-support-library


    【解决方案1】:

    嗯。虽然马雷克的作品并没有直接回答这个问题..

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

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

    只要确保您的 Activity 是 FragmentActivity,您就可以开始新的 Fragment 事务。

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

    【讨论】:

    • 您还需要提交事务 - fft.commit() - 因为您没有使用传递给该方法的 FragmentTransaction。
    • 哇,这完全解决了我在支持库方面的所有问题。
    【解决方案2】:

    关键是用

    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;
            }
        }
    }
    

    【讨论】:

      【解决方案3】:
      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 库。

      【讨论】:

      • 这不起作用,因为选项卡侦听器期望来自 android 3.0 而不是来自支持库的片段和 fragmentTransaction 对象
      【解决方案4】:

      我想实现@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 或更高版本的设备。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-12-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-02
          • 2016-06-07
          相关资源
          最近更新 更多