滑块菜单片段中的可交换选项卡
Posted
技术标签:
【中文标题】滑块菜单片段中的可交换选项卡【英文标题】:Swapable tabs in Slider Menu fragment 【发布时间】:2014-07-03 22:00:24 【问题描述】:我通过引用this tutorial 实现了导航抽屉,现在我想做的是在片段内显示滑动选项卡。即,当我单击导航抽屉中的项目时,假设第一个项目,它应该显示该项目的滑动选项卡。(我的列表视图中有 6 个片段。(同样:- A,B,C,D,E, F). 我的 A 片段上需要 3 个可交换的标签。)
如果 item1 是事件,当我点击它时,它应该显示滑动标签。
但我面临以下问题:-
如何在片段中实现视图分页器?
片段可能会扩展片段。
当 A 片段扩展 FragmentActivity 时,在我的主要活动中,代码显示错误“类型不匹配”,无法从 A 片段转换为片段。
这是我的 Deep.java 文件
package com.amar.demo;
import info.androidhive.slidingmenu.adapter.NavDrawerListAdapter;
import info.androidhive.slidingmenu.model.NavDrawerItem;
import java.util.ArrayList;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
public class Deep extends Activity
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
// nav drawer title
private CharSequence mDrawerTitle;
// used to store app title
private CharSequence mTitle;
// slide menu items
private String[] navMenuTitles;
private TypedArray navMenuIcons;
private ArrayList<NavDrawerItem> navDrawerItems;
private NavDrawerListAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.deep);
mTitle = mDrawerTitle = getTitle();
// load slide menu items
navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);
// nav drawer icons from resources
navMenuIcons = getResources()
.obtainTypedArray(R.array.nav_drawer_icons);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.list_slidermenu);
navDrawerItems = new ArrayList<NavDrawerItem>();
// adding nav drawer items to array
// Home
navDrawerItems.add(new NavDrawerItem(navMenuTitles[0], navMenuIcons
.getResourceId(0, -1)));
// Find People
navDrawerItems.add(new NavDrawerItem(navMenuTitles[1], navMenuIcons
.getResourceId(1, -1)));
// Photos
navDrawerItems.add(new NavDrawerItem(navMenuTitles[2], navMenuIcons
.getResourceId(2, -1)));
// Communities, Will add a counter here
navDrawerItems.add(new NavDrawerItem(navMenuTitles[3], navMenuIcons
.getResourceId(3, -1), true, "22"));
// Pages
navDrawerItems.add(new NavDrawerItem(navMenuTitles[4], navMenuIcons
.getResourceId(4, -1)));
// What's hot, We will add a counter here
navDrawerItems.add(new NavDrawerItem(navMenuTitles[5], navMenuIcons
.getResourceId(5, -1), true, "50+"));
// Recycle the typed array
navMenuIcons.recycle();
mDrawerList.setOnItemClickListener(new SlideMenuClickListener());
// setting the nav drawer list adapter
adapter = new NavDrawerListAdapter(getApplicationContext(),
navDrawerItems);
mDrawerList.setAdapter(adapter);
// enabling action bar app icon and behaving it as toggle button
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_drawer, // nav menu toggle icon
R.string.app_name, // nav drawer open - description for
// accessibility
R.string.app_name // nav drawer close - description for
// accessibility
)
public void onDrawerClosed(View view)
getActionBar().setTitle(mTitle);
// calling onPrepareOptionsMenu() to show action bar icons
invalidateOptionsMenu();
public void onDrawerOpened(View drawerView)
getActionBar().setTitle(mDrawerTitle);
// calling onPrepareOptionsMenu() to hide action bar icons
invalidateOptionsMenu();
;
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (savedInstanceState == null)
// on first time display view for first nav item
displayView(0);
/**
* Slide menu item click listener
* */
private class SlideMenuClickListener implements
ListView.OnItemClickListener
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id)
// display view for selected nav drawer item
displayView(position);
@Override
public boolean onCreateOptionsMenu(Menu menu)
getMenuInflater().inflate(R.menu.testmenu, menu);
return true;
@Override
public boolean onOptionsItemSelected(MenuItem item)
// toggle nav drawer on selecting action bar app icon/title
if (mDrawerToggle.onOptionsItemSelected(item))
return true;
// Handle action bar actions click
switch (item.getItemId())
case R.id.a_More:
return true;
default:
return super.onOptionsItemSelected(item);
/* *
* Called when invalidateOptionsMenu() is triggered
*/
@Override
public boolean onPrepareOptionsMenu(Menu menu)
// if nav drawer is opened, hide the action items
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.a_More).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
/**
* Diplaying fragment view for selected nav drawer list item
* */
private void displayView(int position)
// update the main content by replacing fragments
Fragment fragment = null;
switch (position)
case 0:
fragment = new HomeFragment();
break;
case 1:
fragment = new FindPeopleFragment();
break;
case 2:
fragment = new PhotosFragment();
break;
case 3:
fragment = new CommunityFragment();
break;
case 4:
fragment = new PagesFragment();
break;
case 5:
fragment = new WhatsHotFragment();
break;
default:
break;
if (fragment != null)
FragmentManager fragmentManager = getFragmentManager();
// fragmentManager.beginTransaction()
// .replace(R.id.frame_container, fragment).commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
else
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
@Override
public void setTitle(CharSequence title)
mTitle = title;
getActionBar().setTitle(mTitle);
/**
* When using the ActionBarDrawerToggle, you must call it during
* onPostCreate() and onConfigurationChanged()...
*/
@Override
protected void onPostCreate(Bundle savedInstanceState)
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
@Override
public void onConfigurationChanged(Configuration newConfig)
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggls
mDrawerToggle.onConfigurationChanged(newConfig);
在此代码中,我在案例 0 中遇到问题。
这是我的 HomeFragment 代码:- 包 com.amar.demo;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.amar.demo.adapter.TabsPagerAdapter;
public class HomeFragment extends FragmentActivity implements
ActionBar.TabListener
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = "My Restaurant", "Offers", "Search & Book",
"News & Updates" ;
public HomeFragment()
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
View rootView = inflater.inflate(R.layout.fragment_home, container,
false);
// code of tabes
viewPager = (ViewPager) rootView.findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs)
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener()
@Override
public void onPageSelected(int position)
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
@Override
public void onPageScrolled(int arg0, float arg1, int arg2)
@Override
public void onPageScrollStateChanged(int arg0)
);
return rootView;
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft)
// TODO Auto-generated method stub
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft)
// TODO Auto-generated method stub
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft)
// TODO Auto-generated method stub
这是我的 deep.xml 代码:-
<!-- Framelayout to display Fragments -->
<FrameLayout
android:id="@+id/frame_container"
android:layout_
android:layout_ />
<!-- Listview to display slider menu -->
<ListView
android:id="@+id/list_slidermenu"
android:layout_
android:layout_
android:layout_gravity="start"
android:background="@color/list_background"
android:choiceMode="singleChoice"
android:divider="@color/list_divider"
android:dividerHeight="1dp"
android:listSelector="@drawable/list_selector" />
</android.support.v4.widget.DrawerLayout>
这是我的 homefragment.xml 代码:-
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_
android:layout_>
</android.support.v4.view.ViewPager>
【问题讨论】:
是的..我们可以在片段中实现视图寻呼机... 但是..如何在片段中实现视图寻呼机...?? @Amardeep 看到我的答案,我已经用新代码更新了答案。 不确定您需要多长时间才能支持旧版本的 Android,但子类 FragmentActivity 早已被弃用,现在只需要子类普通 Activity(不确定版本截止)。 【参考方案1】:您必须使用包含 ViewPager 的自定义布局创建片段。
按照这些步骤,它将指导整个过程。
1。创建布局以表示 ViewPager,将其命名为 fragment_main.xml
<TabHost
android:id="@android:id/tabhost"
android:layout_
android:layout_>
<LinearLayout
android:orientation="vertical"
android:layout_
android:layout_>
<TabWidget
android:id="@android:id/tabs"
android:orientation="horizontal"
android:layout_
android:layout_
android:layout_weight="0"/>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_
android:layout_
android:layout_weight="0"/>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_
android:layout_
android:layout_weight="1"/>
</LinearLayout>
</TabHost>
2。创建一个片段来保存上面 XML 上声明的 ViewPager,将其命名为 MyFragment.java
如您所见,我们在上面的 XML 中声明了 TabHost
、ViewPager
和其他元素。同样在这个片段中,我们膨胀了之前创建的布局,并使用TabAdapter
来处理所有选项卡。
import android.content.Context;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TabHost;
import android.widget.TabWidget;
import java.util.ArrayList;
public static class MyFragment extends Fragment
private TabHost mTabHost;
private ViewPager mViewPager;
private TabsAdapter mTabsAdapter;
public MyFragment()
@Override
public void onCreate(Bundle instance)
super.onCreate(instance);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
View v = inflater.inflate(R.layout.fragment_main, container, false);
mTabHost = (TabHost) v.findViewById(android.R.id.tabhost);
mTabHost.setup();
mViewPager = (ViewPager) v.findViewById(R.id.pager);
mTabsAdapter = new TabsAdapter(getActivity(), mTabHost, mViewPager);
// Here we load the content for each tab.
mTabsAdapter.addTab(mTabHost.newTabSpec("one").setIndicator("One"), PageOneFragment.class, null);
mTabsAdapter.addTab(mTabHost.newTabSpec("two").setIndicator("Two"), PageTwoFragment.class, null);
return v;
public static class TabsAdapter extends FragmentPagerAdapter implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener
private final Context mContext;
private final TabHost mTabHost;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo
private final String tag;
private final Class<?> clss;
private final Bundle args;
TabInfo(String _tag, Class<?> _class, Bundle _args)
tag = _tag;
clss = _class;
args = _args;
static class DummyTabFactory implements TabHost.TabContentFactory
private final Context mContext;
public DummyTabFactory(Context context)
mContext = context;
public View createTabContent(String tag)
View v = new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager)
super(activity.getSupportFragmentManager());
mContext = activity;
mTabHost = tabHost;
mViewPager = pager;
mTabHost.setOnTabChangedListener(this);
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args)
tabSpec.setContent(new DummyTabFactory(mContext));
String tag = tabSpec.getTag();
TabInfo info = new TabInfo(tag, clss, args);
mTabs.add(info);
mTabHost.addTab(tabSpec);
notifyDataSetChanged();
@Override
public int getCount()
return mTabs.size();
@Override
public Fragment getItem(int position)
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
public void onTabChanged(String tabId)
int position = mTabHost.getCurrentTab();
mViewPager.setCurrentItem(position);
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
public void onPageSelected(int position)
// Unfortunately when TabHost changes the current tab, it kindly
// also takes care of putting focus on it when not in touch mode.
// The jerk.
// This hack tries to prevent this from pulling focus out of our
// ViewPager.
TabWidget widget = mTabHost.getTabWidget();
int oldFocusability = widget.getDescendantFocusability();
widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
mTabHost.setCurrentTab(position);
widget.setDescendantFocusability(oldFocusability);
public void onPageScrollStateChanged(int state)
如您所见,每个选项卡调用一个特定的片段。这些片段代表每个选项卡的内容。所以让我们创建它们,它们非常简单,并且只包含一个TextView
。
3。为第一个选项卡内容创建一个片段,将其命名为 PageOneFragment.java
此片段将保存第一个选项卡的内容。您可以在此片段中放置任何内容,它将与其他片段和其他选项卡分开。
这里我们在onCreateView
方法中扩充了xml 布局pageone_fragment.xml。我们将在下一步中创建这个 xml 布局。
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class PageOneFragment extends Fragment
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
return inflater.inflate(R.layout.pageone_fragment, container, false);
@Override
public void onActivityCreated(Bundle savedInstanceState)
super.onActivityCreated(savedInstanceState);
@Override
public void onAttach(Activity activity)
super.onAttach(activity);
@Override
public void onStart()
super.onStart();
@Override
public void onResume()
super.onResume();
如前所述,我们必须为这个片段创建布局。
4。为 PageOneFragment 创建布局,将其命名为 pageone_fragment.xml
这只是一个简单的布局,用TextView
表示选项卡的内容。你可以在这个布局中构建任何你想要的东西,它将与其他片段和选项卡分开。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/first_fragment"
android:layout_
android:layout_
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:background="#ff4063ff">
<TextView
android:layout_
android:layout_
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="First Page"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:id="@+id/firstFragmentTextView"
android:layout_gravity="center_horizontal|top" />
</LinearLayout>
因为我们有两个选项卡,所以我们有两个片段,每个选项卡一个。所以让我们为第二个标签内容创建第二个片段。
5。为第二个标签内容创建片段,将其命名为 PageTwoFragment.java
如您所见,我们在 onCreateView
方法上扩展了不同的布局,称为 pagetwo_fragment.xml
。我们将在下一步创建它。
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class PageTwoFragment extends Fragment
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
return inflater.inflate(R.layout.pagetwo_fragment, container, false);
@Override
public void onActivityCreated(Bundle savedInstanceState)
super.onActivityCreated(savedInstanceState);
@Override
public void onAttach(Activity activity)
super.onAttach(activity);
@Override
public void onStart()
super.onStart();
@Override
public void onResume()
super.onResume();
正如我们之前为 PageOneFragment 所做的那样,让我们也为第二个片段创建布局,正如我们之前提到的。
6。为 PageTwoFragment 创建布局,将其命名为 pagetwo_fragment.xml
这是一个简单的布局,只有一个TextView
,只是为了表示内容。你可以在这里构建任何你想要的东西,它将与其他片段和选项卡分开。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/first_fragment"
android:layout_
android:layout_
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:background="#ff4063ff">
<TextView
android:layout_
android:layout_
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Second Page"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:id="@+id/firstFragmentTextView"
android:layout_gravity="center_horizontal|top" />
</LinearLayout>
7。从您的NavigationDrawer
调用此片段
如果你想从你的NavigationDrawer
调用这个片段,在你活动的displayView(int position)
方法的switch
语句中,你应该在你的case
语句之一中执行此操作,例如。
case 0:
fragment = new MyFragment();
break;
这是最终结果
ViewPager
在片段上运行,有两个选项卡,每个选项卡都包含一个具有独特内容的独特片段。
就是这样。
希望对你有所帮助。
【讨论】:
这是一个建议...我希望..,您知道在哪里写答案以及在哪里写建议 @GVSharma 我正在更新我的答案。 我在第 7 步中发现了错误“类型不匹配:无法从 HomeFragment 转换为 Fragment” private void displayView(int position) // 通过替换片段来更新主要内容 Fragment fragment = null; switch (position) case 0: fragment = new HomeFragment();休息; 不。你必须打电话给MyFragment
,而不是HomeFragment
。您创建的片段类的名称是什么?【参考方案2】:
关于第 7 步“类型不匹配”中的错误
制作:
replace **import android.app.Fragment** to **import android.support.v4.app.Fragment**
万一:
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frame_container, fragment).commit();
【讨论】:
【参考方案3】:public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) tabSpec.setContent(new DummyTabFactory(mContext)); String tag = tabSpec.getTag(); TabInfo info = new TabInfo(tag, clss, args); mTabs.add(info); mTabHost.addTab(tabSpec); notifyDataSetChanged();
mTabs 变量的声明位置
谢谢
【讨论】:
以上是关于滑块菜单片段中的可交换选项卡的主要内容,如果未能解决你的问题,请参考以下文章