zoukankan      html  css  js  c++  java
  • Android典型界面设计(8) ——ViewPager+PagerSlidingTabStrip实现双导航

    一、问题描述

      PagerSlidingTabStrip是android开源项目,指示器控件。官网地址:https://github.com/astuetz/PagerSlidingTabStrip

      该组件可和ViewPager结合实现效果不错的滑动式导航,最大特点是滑动条可跟随ViewPager联动,不过PagerSlidingTabStrip只有文字或图片两种,没有提供图片和文字的混合的形式,感觉更适合实现头部的导航,不太适合做底部导航(一般底部导航都是典型的上图下字的导航),不过可以通过修改源码来实现这种图文混合的导航,下面就使用ViewPager+PagerSlidingTabStrip实现如图所示效果:

    二、修改PagerSlidingTabStrip组件

      PagerSlidingTabStrip提供文本指示器和图标指示器两种,即 tab 是 text 还是 icon。如果是 icon 的话,通过 Viewpager 的 adapter 实现接口IconTabProvider重写getPageIconResId方法:

    public  class  MainPagerAdapter  extends  FragmentPagerAdapter   implements 
     IconTabProvider{
            @Override
            public  int  getPageIconResId(int position){
                …
    }
    }

    如果是Text的话,只需重写适配器自身的getPageTitle()方法:

    public  class  MainPagerAdapter  extends  FragmentPagerAdapter  {
            @Override
            public  int  getPageTitle (int position){
                …
    }
    }

    这里我们还需要图文混排的指示器(底部导航需要),因此在源码做如下改动:

    定义接口:

    public interface ViewTabProvider{
            public View getTabView(int position);
        }

    定义属性和set/get方法

    private String[] tabTexts;//存储所有指示器的文本内容
    private int normalIconRes[];//存储所有指示器未选择的图标
        private int lightIconRes[];//存储所有指示器已选择的图标
    修改notifyDataSetChanged()方法(红色部分为更改代码):
    for (int i = 0; i < tabCount; i++) {
                if (pager.getAdapter() instanceof IconTabProvider) {
                    addIconTab(i, ((IconTabProvider) pager.getAdapter())
                            .getPageIconResId(i));
                } else if(pager.getAdapter() instanceof ViewTabProvider){
                    addViewTab(i, ((ViewTabProvider)pager.getAdapter()).getTabView(i));    
                }else {
                    addTextTab(i, pager.getAdapter().getPageTitle(i).toString());
                }
            }

      添加addViewTab()方法:实现将tab添加到指示器中,并为tab注册单击事件,当单击tab时ViewPager翻页,并调用updateTabStyles()更新Tab的样式

           private int currentIdx=0;//记录当前指示器的索引值
    private void addViewTab(final int position, View tab){
            tab.setFocusable(true);
            tab.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    pager.setCurrentItem(position);
                    currentIdx=position;
                    updateTabStyles();
                }
            });
        tab.setPadding(tabPadding, 0, tabPadding, 0);
        tabsContainer.addView(tab, position, shouldExpand ? expandedTabLayoutParams : defaultTabLayoutParams);
        }

    添加setSelectedTextColor()以便设置已选择指示器的字体颜色

    private  int  tabSelectedTextColor;//表示已选择的文本字体颜色
    public  void  setSelectedTextColor(int color){
            this.tabSelectedTextColor=color;
            updateTabStyles();
    }

    修改updateTabStyles()方法,红色部分为变更代码

    if (v instance  of  TextView) {
            TextView tab = (TextView) v;
            tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabTextSize);
            tab.setTypeface(tabTypeface, tabTypefaceStyle);
            tab.setTextColor(tabTextColor);
            if(i==0 && tabSelectedTextColor!=0){
                        tab.setTextColor(tabSelectedTextColor);
                }
                if (textAllCaps) {
                    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                        tab.setAllCaps(true);
                    } else {
                        tab.setText(tab.getText().toString().toUpperCase(locale));
                    }
                }
    }else if(v  instanceof  ViewGroup){
        ImageView tabIcon=(ImageView)v.findViewById(android.R.id.icon);
        TextView tabTxt=(TextView)v.findViewById(android.R.id.title);
        tabTxt.setText(tabTexts[i]);
        if(currentIdx==i){
                tabIcon.setImageResource(this.lightIconRes[i]);
                tabTxt.setTextColor(tabSelectedTextColor);
        }else{
                tabTxt.setTextColor(tabTextColor);
                tabIcon.setImageResource(this.normalIconRes[i]);
            }
        }
        }
    三、MainActivity部分,实现外层底部导航

    1、MainActivity布局文件,指示器在底部

    <RelativeLayout 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"
        tools:context=".MainActivity" >
            <com.example.pagerslidingtabscripdemo.view.MyViewPager
            android:id="@+id/newsPager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
             android:layout_above="@+id/newsTabs"
            />
            <com.astuetz.PagerSlidingTabStrip
                android:id="@+id/newsTabs"
                android:layout_width="match_parent"
                android:layout_height="48dp"
                android:background="@drawable/backgroud_tabs"
                android:layout_alignParentBottom="true"
                />
    </RelativeLayout>

    2、重写ViewPager方法,实现禁止ViewPager滑动

    public class MyViewPager extends ViewPager {
        private boolean isPagingEnable=true;
        public MyViewPager(Context context,AttributeSet attrs) {
            super(context,attrs);
        }
        public MyViewPager(Context context){
            super(context);
        }
        @Override
        public boolean onTouchEvent(MotionEvent event){
            return this.isPagingEnable&&super.onTouchEvent(event);
        }
        @Override
        public boolean onInterceptTouchEvent(MotionEvent event){
            return this.isPagingEnable&&super.onInterceptTouchEvent(event);
        }
        public void setPagingEnabled(boolean enable){
            this.isPagingEnable=enable;
        }
    }

    3、MainActivity代码:

    private PagerSlidingTabStrip tabs;
        private MyViewPager pages;
        private List<Fragment> fragmentList;
        private MainPagerAdapter adapter;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            tabs=(PagerSlidingTabStrip)super.findViewById(R.id.newsTabs);
            pages=(MyViewPager)super.findViewById(R.id.newsPager);
            fragmentList=new ArrayList<Fragment>();
            initView();
            
        }
    
        
        private void initView(){
            initFragment();
            adapter=new MainPagerAdapter(super.getSupportFragmentManager(),
                    fragmentList, this);
            pages.setAdapter(adapter);
            pages.setPagingEnabled(false);
            tabs.setNormalIconRes(TabsData.normalIconRes);//设置未选择的图标
            tabs.setLightIconRes(TabsData.lightIconRes);//设置已选择的图标
            tabs.setTabTexts(TabsData.boards);//设置文本
            tabs.setViewPager(pages);//与ViewPager关联,这样指示器就可以和ViewPager联动
            tabs.setSelectedTextColor(Color.RED);//设置当前选择的tab的文本颜色
            tabs.setIndicatorColor(Color.TRANSPARENT);//去除指示器的底部横线
            tabs.setDividerColor(Color.TRANSPARENT);//去除tab间的分割线
        }
    
        private void initFragment(){
            fragmentList=new ArrayList<Fragment>();
            fragmentList.add(new NewsFragment());
            for(int i=1;i<TabsData.boards.length;i++){
                Bundle bundle=new Bundle();
                bundle.putString("title", TabsData.boards[i]);
                CommentFragment fragment=new CommentFragment();
                fragment.setArguments(bundle);
                fragmentList.add(fragment);
            }
        }

    4、TabsData数据:

    public class TabsData {
        public  static  String[]  boards={"新闻","阅读","试听","发现"," 我"};
        public  static int[]  normalIconRes={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};
        Public  static  int[]  lightIconRes={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}; 
    }

    5、MainPagerAdapter适配器:

    public class MainPagerAdapter extends FragmentPagerAdapter 
    implements ViewTabProvider {
        private List<Fragment> fragmentList;
        private Context context;
        public MainPagerAdapter(FragmentManager fm,List<Fragment> fragmentList,Context context) {
            super(fm);
            this.fragmentList=fragmentList;
            this.context=context;    }
        @Override
        public Fragment getItem(int arg0) {
            return fragmentList.get(arg0);
        }
        @Override
        public int getCount() {
            return fragmentList.size();    }
        @Override
        public View getTabView(int position) {
            View view=LayoutInflater.from(context).inflate(R.layout.footer_tabs, null);
            return view;
    }
    }

    6、CommentFragment代码:

    public class CommentFragment extends Fragment {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
        }
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            TextView tvTitle=new TextView(super.getActivity());
            tvTitle.setText(title);
            tvTitle.setLayoutParams(new LayoutParams(
                    LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
            tvTitle.setGravity(Gravity.CENTER);
            tvTitle.setTextSize(20);
            return tvTitle;
        }
        private String title;
        @Override
        public void setArguments(Bundle bundle) {
            title=bundle.getString("title");
        }
    }
    四、NewsFragment 实现内层头部导航

    1、Xml文件:

    <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" >
        <com.astuetz.PagerSlidingTabStrip
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:background="@drawable/backgroud_tabs"
            />
        <android.support.v4.view.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            />
    </LinearLayout>

      注意:fragment中使用PagerSlidingTabStrip组件须采用LinearLayout布局,不能使用相对布局

    2、代码:

    public  class NewsFragment extends Fragment {
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
        }
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
        private View view;
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            if(view==null){
                view=inflater.inflate(R.layout.news_fragment, null);
                ViewPager pages=(ViewPager)view.findViewById(R.id.pager);
                PagerSlidingTabStrip tabs=(PagerSlidingTabStrip)view.findViewById(R.id.tabs);
                initFragment();
                adapter=new ChannelPagerAdapter(super.getActivity().getSupportFragmentManager(),
                        fragmentList, titles);
                pages.setAdapter(adapter);
                tabs.setViewPager(pages);
                tabs.setSelectedTextColor(Color.RED);            
                tabs.setDividerColor(Color.TRANSPARENT);
                tabs.setIndicatorColor(Color.RED);
            }
            ViewGroup parent=(ViewGroup)view.getParent();
            if(parent!=null){
                parent.removeView(view);
            }
            return view;
        }
        private ChannelPagerAdapter adapter;
        private List<Fragment> fragmentList;
        private String[] titles={"头条","娱乐","体育","财经","热点","科技"};
        private void initFragment(){
            Fragment fragment=null;
            fragmentList=new ArrayList<Fragment>();
            for(String title: titles){
                fragment=new ChannelNewsFragment();
                Bundle bundle=new Bundle();
                bundle.putString("title",title);
                fragment.setArguments(bundle);
                fragmentList.add(fragment);
            }
        }
    
    }

    3、  ChannelNewsFragment

    public class ChannelNewsFragment extends Fragment {
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
        public void onAttach(Activity activity) {
            super.onAttach(activity);
        }
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            TextView tvTitle=new TextView(super.getActivity());
            tvTitle.setText(title);
            tvTitle.setLayoutParams(new LayoutParams(
                    LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
            tvTitle.setGravity(Gravity.CENTER);
            tvTitle.setTextSize(20);
            return tvTitle;
        }
        private String title;
        public void setArguments(Bundle bundle) {
            title=bundle.getString("title");
        }
    }
    作者:杰瑞教育
    出处:http://www.cnblogs.com/jerehedu/ 
    版权声明:本文版权归烟台杰瑞教育科技有限公司和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    技术咨询:JRedu技术交流
     
  • 相关阅读:
    PHP 数组对象 按照某个字段进行排序
    laravel 多条件查询
    PHP QR CODE 类库生成二维码
    TypeError:Cannot read property 'type' of undefined
    input禁止输入的4种方法
    QQ会话调用地址
    禁止左右键复制
    设置Meta标签 清除页面缓存
    百度统计,百度自动推送合并
    强制使用360浏览器 使用webkit内核
  • 原文地址:https://www.cnblogs.com/jerehedu/p/4863319.html
Copyright © 2011-2022 走看看