Android 使用支持库实现 TabListener
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12721949/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Implementing a TabListener using the Support Library
提问by daniel_c05
I am trying to implement Tab Navigation, but I want to make sure people that have older versions of Android can still use my application.
我正在尝试实现 Tab Navigation,但我想确保使用旧版 Android 的人仍然可以使用我的应用程序。
The app in mind ATM is fairly simple, I just want to be able to understand how to implement the layout and then I'll add the missing bits.
ATM 中的应用程序相当简单,我只想了解如何实现布局,然后我将添加缺少的部分。
Anyhow, I have a Container Activity that extends Fragment Activity(to ensure compatibility), and this Activity creates a TabView using an ActionBar(I believe my problem resides here). The app will try to create three tabs and add them to the ActionBar, and I want to make sure the user can scroll back and forth using lateral navigation.
无论如何,我有一个扩展Fragment Activity的 Container Activity (以确保兼容性),并且该 Activity 使用ActionBar创建了一个 TabView (我相信我的问题出在此处)。该应用程序将尝试创建三个选项卡并将它们添加到 ActionBar,我想确保用户可以使用横向导航来回滚动。
Here is TabListener I am trying to implement:
这是我正在尝试实现的 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) {
}
}
Here are my imports, because I wanted to make sure I was using the support library:
这是我的导入,因为我想确保我使用的是支持库:
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;
However, Eclipse is giving me issues with the TabListenermethods. It is telling me the following: "The type LayoutContainer.TabListener must implement the inherited abstract method ActionBar.TabListener.onTabSelected(ActionBar.Tab, FragmentTransaction)"
但是,Eclipse 给我带来了TabListener方法的问题。它告诉我以下内容:“类型 LayoutContainer.TabListener 必须实现继承的抽象方法 ActionBar.TabListener.onTabSelected(ActionBar.Tab, FragmentTransaction)”
When I select Add unimplemented methodsEclipse basically adds the OnTabSelected OnTabReselectedand OnTabUnselectedmethods, but this time, passing the non-support version of the Fragment (android..app.Fragment) as a parameter.
当我选择添加未实现的方法时,Eclipse 基本上添加了OnTabSelected OnTabReselected和OnTabUnselected方法,但这一次,将非支持版本的 Fragment ( android..app.Fragment) 作为参数传递。
Any ideas on how to make another implementation of lateral navigation through the support library to ensure compatibility?
关于如何通过支持库进行横向导航的另一个实现以确保兼容性的任何想法?
采纳答案by Malek Hijazi
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);
The tab listener is as follows:
选项卡侦听器如下:
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);
}
}
and then you make a class for each tab:
然后为每个选项卡创建一个类:
public class BFragmentTab extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.inflate(R.layout.login, container, false);
}
}
But keep in mind that the action bar isn't supported for android versions below 3.0 . If you want to use it in older versions I suggest you use actionBarSherlock Library.
但请记住,低于 3.0 的 android 版本不支持操作栏。如果您想在旧版本中使用它,我建议您使用 actionBarSherlock 库。
回答by Nelson Ramirez
hmmm. while Malek's works it doesn't directly answer the question..
嗯。虽然马利克的作品并没有直接回答这个问题..
You can simply ignore the fragment transaction you get in the callback and use your own:
您可以简单地忽略您在回调中获得的片段交易并使用您自己的:
android.support.v4.app.FragmentTransaction fft = mActivity.getSupportFragmentManager().beginTransaction();
Just make sure that your activity is a FragmentActivity and you'll be able to start a new fragment transaction.
只需确保您的活动是 FragmentActivity,您就可以开始新的 Fragment 事务。
Also the replace() method in the fragmentTransaction is much more convenient than add() and remove()
而且 fragmentTransaction 中的 replace() 方法比 add() 和 remove() 方便得多
回答by John Bentley
The key is to use
关键是用
import android.support.v7.app.ActionBar;
... rather than ...
... 而不是 ...
import android.app.ActionBar;
That avoids the clever workaround Nelson Ramirez posted.
这避免了纳尔逊·拉米雷斯 (Nelson Ramirez) 发布的巧妙解决方法。
The following full example, based on the official documentation, was tested to work from Android 3.0, API 11
以下完整示例基于官方文档,经过测试可在 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;
}
}
}
回答by Anna Billstrom
I wanted to implement @nelson-ramirez but had an error accessing mActivity, so this is a combination of those two answers, and works for my project, which uses a tab navigation with Facebook login (which requires support.v4 library). the keys are, creating a private mActivity that you then pass in and assign when initiating the listener, and creating your own Fragment Transaction, not using the one from the argument. Also, change the main activity to FragmentActivity, using v4 library, which allows access to getSupportFragmentManager().
我想实现 @nelson-ramirez 但访问 mActivity 时出错,所以这是这两个答案的组合,适用于我的项目,该项目使用带有 Facebook 登录的标签导航(需要 support.v4 库)。关键是,创建一个私有 mActivity,然后在启动侦听器时传入并分配该 mActivity,并创建您自己的 Fragment Transaction,而不是使用参数中的那个。此外,使用允许访问 getSupportFragmentManager() 的 v4 库将主活动更改为 FragmentActivity。
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) {
}
}
回答by serv-inc
Any ideas on how to make another implementation of lateral navigation through the support library to ensure compatibility?
关于如何通过支持库进行横向导航的另一个实现以确保兼容性的任何想法?
Alternative solution
替代方案
As of 29 May 2015, you can use the Android Design Support Library. It includes a Tab Layoutand supports Android 2.1 or higher devices.
自 2015 年 5 月 29 日起,您可以使用 Android 设计支持库。它包括选项卡布局并支持 Android 2.1 或更高版本的设备。