Android开发中ViewPage+Fragment实现区域顶部tab滑动切换
本教程我们将说说tab导航,导航分为一层和两层(底部区块+区域内头部导航),主要实现方案有RadioGroup+ViewPage+Fragment、Viewpager Indicator、ActionBar Tabs、FragmentTabHost+Fragment等,下面我们先采用RadioGroup+ViewPage+Fragment实现区域头部导航。
如图所示:
案例主要组件
1、先看一下MainActivity布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <HorizontalScrollView android:id="@+id/hvChannel" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="none" > <RadioGroup android:id="@+id/rgChannel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> </RadioGroup> </HorizontalScrollView> <android.support.v4.view.ViewPager android:id="@+id/vpNewsList" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > </android.support.v4.view.ViewPager> </LinearLayout>
2、MainActivity代码:
public class MainActivity extends FragmentActivity implements OnPageChangeListener{ private ViewPager viewPager; private RadioGroup rgChannel=null; private HorizontalScrollView hvChannel; private PageFragmentAdapter adapter=null; private List<Fragment> fragmentList=new ArrayList<Fragment>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView(){ rgChannel=(RadioGroup)super.findViewById(R.id.rgChannel); viewPager=(ViewPager)super.findViewById(R.id.vpNewsList); hvChannel=(HorizontalScrollView)super.findViewById(R.id.hvChannel); rgChannel.setOnCheckedChangeListener( new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { viewPager.setCurrentItem(checkedId); } }); viewPager.setOnPageChangeListener(this); initTab();//动态产生RadioButton initViewPager(); rgChannel.check(0); } private void initTab(){ List<Channel> channelList=ChannelDb.getSelectedChannel(); for(int i=0;i<channelList.size();i++){ RadioButton rb=(RadioButton)LayoutInflater.from(this). inflate(R.layout.tab_rb, null); rb.setId(i); rb.setText(channelList.get(i).getName()); RadioGroup.LayoutParams params=new RadioGroup.LayoutParams(RadioGroup.LayoutParams.WRAP_CONTENT, RadioGroup.LayoutParams.WRAP_CONTENT); rgChannel.addView(rb,params); } } private void initViewPager(){ List<Channel> channelList=ChannelDb.getSelectedChannel(); for(int i=0;i<channelList.size();i++){ NewsFragment frag=new NewsFragment(); Bundle bundle=new Bundle(); bundle.putString("weburl", channelList.get(i).getWeburl()); bundle.putString("name", channelList.get(i).getName()); frag.setArguments(bundle); //向Fragment传入数据 fragmentList.add(frag); } adapter=new PageFragmentAdapter(super.getSupportFragmentManager(),fragmentList); viewPager.setAdapter(adapter); //viewPager.setOffscreenPageLimit(0); } /** * 滑动ViewPager时调整ScroollView的位置以便显示按钮 * @param idx */ private void setTab(int idx){ RadioButton rb=(RadioButton)rgChannel.getChildAt(idx); rb.setChecked(true); int left=rb.getLeft(); int width=rb.getMeasuredWidth(); DisplayMetrics metrics=new DisplayMetrics(); super.getWindowManager().getDefaultDisplay().getMetrics(metrics); int screenWidth=metrics.widthPixels; int len=left+width/2-screenWidth/2; hvChannel.smoothScrollTo(len, 0);//滑动ScroollView } @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int position) { // TODO Auto-generated method stub setTab(position); } }
其中initTab()方法实现向RadioGroup动态添加RadioButton
导航按钮数据来源于ChannelDb
private static List<Channel> selectedChannel=new ArrayList<Channel>(); static{ selectedChannel.add(new Channel("","头条",0,"","")); selectedChannel.add(new Channel("","娱乐",0,"","")); selectedChannel.add(new Channel("","体育",0,"","")); selectedChannel.add(new Channel("","财经",0,"","")); selectedChannel.add(new Channel("","热点",0,"","")); selectedChannel.add(new Channel("","科技",0,"","")); selectedChannel.add(new Channel("","图片",0,"","")); selectedChannel.add(new Channel("","汽车",0,"","")); selectedChannel.add(new Channel("","时尚",0,"","")); } public static List<Channel> getSelectedChannel(){ return selectedChannel; }
导航按钮外观:tab_rb.xml和tab_selector.xml背景选择器(实现选择后带红色下划线效果)
<?xml version="1.0" encoding="utf-8"?> <RadioButton xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="30dp" android:text="今日" android:background="@drawable/tab_selector" android:paddingLeft="15dp" android:paddingRight="15dp" android:paddingTop="10dp" android:paddingBottom="10dp" android:button="@null" /> tab_selector.xml: <selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:state_checked="true" ><!-- 选中状态 --> <layer-list > <item > <shape android:shape="rectangle"> <stroke android:width="5dp" android:color="#ff0000"/> </shape> </item> <item android:bottom="5dp" > <shape android:shape="rectangle" > <solid android:color="#fff"/> </shape> </item> </layer-list> </item> <item ><!-- 默认状态 --> <shape > <solid android:color="#FAFAFA"/> </shape> </item> </selector>
3、PageFragmentAdapter适配器
public class PageFragmentAdapter extends FragmentPagerAdapter{ private List<Fragment> fragmentList; private FragmentManager fm; public PageFragmentAdapter(FragmentManager fm,List<Fragment> fragmentList){ super(fm); this.fragmentList=fragmentList; this.fm=fm; } @Override public Fragment getItem(int idx) { return fragmentList.get(idx%fragmentList.size()); } @Override public int getCount() { return fragmentList.size(); } @Override public int getItemPosition(Object object) { return POSITION_NONE; //没有找到child要求重新加载 } }
4、NewsFragment组件:
public class NewsFragment extends Fragment { private String weburl; private String channelName; @Override public void onAttach(Activity activity) { super.onAttach(activity); } private View view; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if(view==null){//优化View减少View的创建次数 //该部分可通过xml文件设计Fragment界面,再通过LayoutInflater转换为View组件 //这里通过代码为fragment添加一个TextView TextView tvTitle=new TextView(getActivity()); tvTitle.setText(channelName); tvTitle.setTextSize(16); tvTitle.setGravity(Gravity.CENTER); tvTitle.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT)); view=tvTitle; } ViewGroup parent=(ViewGroup)view.getParent(); if(parent!=null){//如果View已经添加到容器中,要进行删除,负责会报错 parent.removeView(view); } return view; } @Override public void setArguments(Bundle bundle) {//接收传入的数据 weburl=bundle.getString("weburl"); channelName=bundle.getString("name"); } }
Android开发中FragmentTabHost+Fragment实现底部tab切换
上面我们使用RadioGroup+ViewPage+Fragmen实现了顶部滑动导航,接下来我们使用FragmentTabHost+Fragment实现底部tab切换,效果如图所示
案例主要组件
1、MainActivity布局
把整个Activity分成两部TabHost和TabContent,TabHost包含各个tab,tab之间切换将在TabContent所关联的FrameLayout区域中显示各自板块的内容
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <FrameLayout android:id="@+id/contentLayout" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> </FrameLayout> <android.support.v4.app.FragmentTabHost android:id="@android:id/tabhost" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#F6F6F6" > <FrameLayout android:id="@android:id/tabcontent" android:layout_height="0dp" android:layout_width="0dp" /> </android.support.v4.app.FragmentTabHost> </LinearLayout>
2、MainActivity代码
public class MainActivity extends FragmentActivity implements OnTabChangeListener{ private FragmentTabHost tabHost; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tabHost=(FragmentTabHost)super.findViewById(android.R.id.tabhost); tabHost.setup(this,super.getSupportFragmentManager() ,R.id.contentLayout); tabHost.getTabWidget().setDividerDrawable(null); tabHost.setOnTabChangedListener(this); initTab(); } private void initTab(){ String tabs[]=TabDb.getTabsTxt(); for(int i=0;i<tabs.length;i++){ TabSpec tabSpec=tabHost.newTabSpec(tabs[i]).setIndicator(getTabView(i)); tabHost.addTab(tabSpec,TabDb.getFragments()[i],null); tabHost.setTag(i); } } private View getTabView(int idx){ View view=LayoutInflater.from(this).inflate(R.layout.footer_tabs,null); ((TextView)view.findViewById(R.id.tvTab)).setText(TabDb.getTabsTxt()[idx]); if(idx==0){ ((TextView)view.findViewById(R.id.tvTab)).setTextColor(Color.RED); ((ImageView)view.findViewById(R.id.ivImg)).setImageResource(TabDb.getTabsImgLight()[idx]); }else{ ((ImageView)view.findViewById(R.id.ivImg)).setImageResource(TabDb.getTabsImg()[idx]); } return view; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onTabChanged(String tabId) { // TODO Auto-generated method stub updateTab(); } private void updateTab(){ TabWidget tabw=tabHost.getTabWidget(); for(int i=0;i<tabw.getChildCount();i++){ View view=tabw.getChildAt(i); ImageView iv=(ImageView)view.findViewById(R.id.ivImg); if(i==tabHost.getCurrentTab()){ ((TextView)view.findViewById(R.id.tvTab)).setTextColor(Color.RED); iv.setImageResource(TabDb.getTabsImgLight()[i]); }else{ ((TextView)view.findViewById(R.id.tvTab)).setTextColor(getResources().getColor(R.color.foot_txt_gray)); iv.setImageResource(TabDb.getTabsImg()[i]); } } } }
3、TabDb组件
提供界面设计所需的tab文本、tab图片和Fragment类型数据
public class TabDb { public static String[] getTabsTxt(){ String[] tabs={"新闻","阅读","试听","发现"," 我"}; return tabs; } public static int[] getTabsImg(){ int[] ids={R.drawable.foot_news_normal,R.drawable.foot_read_normal,R.drawable.foot_vdio_normal,R.drawable.foot_fond_normal,R.drawable.foot_out_normal}; return ids; } public static int[] getTabsImgLight(){ int[] ids={R.drawable.foot_news_light,R.drawable.foot_read_light,R.drawable.foot_vdio_light,R.drawable.foot_found_light,R.drawable.foot_out_light}; return ids; } public static Class[] getFragments(){ Class[] clz={NewsFragment.class,ReadFragment.class,VideoFragment.class,FoundFragment.class,OwnerFragment.class}; return clz; } }
4、每个tab各自对应的Fragment组件
共5个Fragment为NewsFragment、ReadFragment、FoundFragment、OwnerFragment、VideoFragment,根据不同板块各自设计界面,这里重点是如何实现底部tab切换,简单布局一下即可,以NewsFragment为例代码如下:
public class NewsFragment extends Fragment { @Override public void onAttach(Activity activity) { // TODO Auto-generated method stub super.onAttach(activity); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub TextView tvTitle=new TextView(super.getActivity()); tvTitle.setText("新闻"); tvTitle.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT)); tvTitle.setGravity(Gravity.CENTER); tvTitle.setTextSize(30); return tvTitle; } @Override public void setArguments(Bundle args) { // TODO Auto-generated method stub super.setArguments(args); } }
5、tab布局样式(footer_tabs.xml)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:padding="5dp" android:background="#F6F6F6" > <ImageView android:id="@+id/ivImg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" /> <TextView android:id="@+id/tvTab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/ivImg" android:textColor="#AEAEAE" android:text="新闻" android:layout_marginTop="2dp"/>
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索int
, view
, 导航
, this
null
fragmenttabhost 底部、fragmenttabhost 顶部、fragmenttabhost 滑动、fragmenttabhost、fragmenttabhost用法,以便于您获取更多的相关知识。