使用ViewPager和Fragment实现底部导航滑动重构版

本文参考自点击这里,对其进行了重构,写下思路,供自己以后思考。

自定义view

设置每个页面的子item

layout_tab_item.xml,每个item由一个ImageView和一个TextView组成


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true">

        <ImageView
            android:id="@+id/tabImg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true" />

        <TextView
            android:id="@+id/tabText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tabImg"
            android:layout_centerHorizontal="true"
            android:text="@string/app_name"
            android:textColor="@android:color/white"
            android:textSize="16sp" />

    RelativeLayout>

RelativeLayout>

设置整个底部导航栏

layout_bottom.xml,底部导航栏由5个item组成


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="70dp"
              android:orientation="horizontal">

    <include
        android:id="@+id/homeLayout"
        layout="@layout/layout_tab_item"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <include
        android:id="@+id/chosenLayout"
        layout="@layout/layout_tab_item"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <include
        android:id="@+id/searchLayout"
        layout="@layout/layout_tab_item"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <include
        android:id="@+id/localLayout"
        layout="@layout/layout_tab_item"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <include
        android:id="@+id/settingLayout"
        layout="@layout/layout_tab_item"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" />

LinearLayout>

创建自定义View并配置

这里用的是bufferKnife注解功能,不懂的请移步谷歌。主要需要注意的就是需要设置很多id的BackgroundResource和TextColor,这里我把需要重复设置的地方进行了重构,知道这点就很容易看懂了。下面多了一处回调接口,主要用于实现点击item时viewpager滑动,即fragment滑动

/**
 * 底部自定义view
 * Created by yyg on 2016/4/22.
 */
public class MyBottomLayout extends LinearLayout implements View.OnClickListener{
    private Context context;
    private RelativeLayout homeLayout;
    private RelativeLayout chosenLayout;
    private RelativeLayout searchLayout;
    private RelativeLayout localLayout;
    private RelativeLayout settingLayout;
    private ICallbackListener iCallbackListener = null;

    public MyBottomLayout(Context context) {
        super(context);
        this.context = context;
        initView();
    }

    public MyBottomLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        initView();
    }

    public MyBottomLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        initView();
    }

    /**
     * 初始化
     */
    private void initView(){
        View view = LayoutInflater.from(context).inflate(R.layout.layout_bottom, this);
        findView(view);
        initData();
        initListener();
    }

    /**
     * 初始化数据
     */
    private void initData() {
        setResidAndColor(0);
    }

    /**
     * 把所有的数据整合一起进行抽取
     */
    private void changeDataItem(int[] resid, int[] color) {
        initDataItem(homeLayout, resid[0], "首页", color[0]);
        initDataItem(chosenLayout, resid[1], "精选", color[1]);
        initDataItem(searchLayout, resid[2], "搜索", color[2]);
        initDataItem(localLayout, resid[3], "本地", color[3]);
        initDataItem(settingLayout, resid[4], "设置", color[4]);
    }

    /**
     * 初始化数据的抽取方法
     * @param resid
     * @param name
     * @param color
     */
    private void initDataItem(View view, int resid, String name, int color) {
        view.findViewById(R.id.tabImg).setBackgroundResource(resid);
        TextView tv = (TextView) view.findViewById(R.id.tabText);
        tv.setText(name);
        tv.setTextColor( (color == 1) ? Color.BLUE : Color.WHITE);
    }

    /**
     * 找到控件的方法
     *
     * @param view
     */
    private void findView(View view) {
        homeLayout = (RelativeLayout) view.findViewById(R.id.homeLayout);
        chosenLayout = (RelativeLayout) view.findViewById(R.id.chosenLayout);
        searchLayout = (RelativeLayout) view.findViewById(R.id.searchLayout);
        localLayout = (RelativeLayout) view.findViewById(R.id.localLayout);
        settingLayout = (RelativeLayout) view.findViewById(R.id.settingLayout);
    }

    /**
     * 控件的监听事件
     */
    private void initListener() {
        homeLayout.setOnClickListener(this);
        chosenLayout.setOnClickListener(this);
        searchLayout.setOnClickListener(this);
        localLayout.setOnClickListener(this);
        settingLayout.setOnClickListener(this);
    }

    /**
     * 控件的点击事件
     * 点击后改变显示的图标和文字的颜色
     * @param v
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.homeLayout:
                setResidAndColor(0);
                break;
            case R.id.chosenLayout:
                setResidAndColor(1);
                break;
            case R.id.searchLayout:
                setResidAndColor(2);
                break;
            case R.id.localLayout:
                setResidAndColor(3);
                break;
            case R.id.settingLayout:
                setResidAndColor(4);
                break;
        }

        //这里加入了一个接口方法,留给ViewPager去实现
        //功能是点击item后viewPager也会跟着变
        iCallbackListener.click(v.getId());
    }

    /**
     * 设置Res和Color
     * @param i
     */
    public void setResidAndColor(int i) {
        switch (i) {
            case 0:
                changeDataItem(setResid(new int[] {1, 0, 0, 0, 0}),
                        new int[] {1, 0, 0, 0, 0});
                break;
            case 1:
                changeDataItem(setResid(new int[] {0, 1, 0, 0, 0}),
                        new int[] {0, 1, 0, 0, 0});
                break;
            case 2:
                changeDataItem(setResid(new int[] {0, 0, 1, 0, 0}),
                        new int[] {0, 0, 1, 0, 0});
                break;
            case 3:
                changeDataItem(setResid(new int[] {0, 0, 0, 1, 0}),
                        new int[] {0, 0, 0, 1, 0});
                break;
            case 4:
                changeDataItem(setResid(new int[] {0, 0, 0, 0, 1}) ,
                        new int[] {0, 0, 0, 0, 1});
                break;
        }
    }

    /**
     * 统一设置Res的地方,留有参数和返回值
     * @param resid 数组,1表示选中,0表示未选中,导航页5个item都要进行判断
     * @return 返回当前设置的Res,作为changeDataItem的参数
     */
    public int[] setResid(int[] resid) {
       int resHome =  (resid[0] == 1) ?  R.mipmap.image_tabbar_button_home_down : R.mipmap.image_tabbar_button_home;
       int resChosen =  (resid[1] == 1) ?  R.mipmap.image_tabbar_button_chosen_down : R.mipmap.image_tabbar_button_chosen;
       int resSearch =  (resid[2] == 1) ?  R.mipmap.image_tabbar_button_search_down : R.mipmap.image_tabbar_button_search;
       int resLocal =  (resid[3] == 1) ?  R.mipmap.image_tabbar_button_local_down : R.mipmap.image_tabbar_button_local;
       int resSetting =  (resid[4] == 1) ?  R.mipmap.image_tabbar_button_setting_down : R.mipmap.image_tabbar_button_setting;
       return new int[] {resHome, resChosen, resSearch, resLocal, resSetting};
    }

    //初始化接口,由需要实现activity(MainActivity)调用
    //通过findviewbyid获取MyBottomLayout,进行调用
    public void setOnCallbackListener(ICallbackListener iCallbackListener) {
        this.iCallbackListener = iCallbackListener;
    }
    //自定义接口文件,click方法由调用处实现,功能是完成viewpager的滑动
    public interface ICallbackListener {
        public void click(int id);
    }
}

实现ViewPager和Fragment的滑动

创建fragment布局和fragment类

此处以home_fragment.xml和HomeFragment为例

home_fragment.xml
----------------------------------
"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    "true"
        android:text="首页"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />



HomeFragment
----------------------------------
/**
 * 主页
 * Created by yyg on 2016/4/22.
 */
public class HomeFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.home_fragment, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }
}

创建activity_main.xml

记得ViewPager和刚刚自定义的MyBottomLayout都要导入类全名


<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=".activity.MainActivity">

    <android.support.v4.view.ViewPager
        android:id="@+id/myViewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/myBottomLayout" />

    <com.buaa.yyg.baidupager.view.MyBottomLayout
        android:id="@+id/myBottomLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@mipmap/image_titlebar_background" />

RelativeLayout>

创建BaseActivity

这一步可以省略,不过为了代码的可复用性建议加上,方便功能的添加

/**
 * Created by yyg on 2016/4/22.
 */
public abstract class BaseActivity extends AppCompatActivity implements View.OnClickListener{

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initView();
        initData();
        initListener();
    }

    @Override
    public void onClick(View v) {
        progress();
    }

    public abstract void initView();
    public abstract void initData();
    public abstract void initListener();
    public abstract void progress();
}

配置MainActivity

需要注意的是使用了butterknife,其他初始化数据方法都需要在其之后执行。
实现了前面的回调监听接口,通过ViewPager方法改变当前的item值,实现自定义view时点击导航item改变页面的功能。
ViewPager使用addOnPageChangeListener进行页面的滑动监听,实现功能滑动时导航item跟着变化。

public class MainActivity extends BaseActivity {

    @Bind(R.id.myViewPager)
    ViewPager myViewPager;
    @Bind(R.id.myBottomLayout)
    MyBottomLayout myBottomLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        //super必须在最后,这样先setContentView然后super到
        //BaseActivity的onCreate,之后才会调用initData等方法
        //不这样会报空指针异常
        super.onCreate(savedInstanceState);
    }

    @Override
    public void initView() {
    }

    @Override
    public void initData() {
        myViewPager.setAdapter(new MyFragmentAdapter(getSupportFragmentManager()));
    }

    @Override
    public void initListener() {
        //设值注入,初始化MyBottomLayout页面的回调实例
        myBottomLayout.setOnCallbackListener(new MyCallBackListener());

        //ViewPager页面监听 使用add而不是set
        myViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                //0是静止,1是正在滑动,2是停止滑动
                if (state == 2) {
                    //设置滑动ViewPager导航同步变化
                    myBottomLayout.setResidAndColor(myViewPager.getCurrentItem());
                }
            }
        });
    }

    /**
     * 实现回调监听方法,用于改变当前item值
     * 在FragmentPagerAdapter的getItem方法中切换Fragment
     */
    private class MyCallBackListener implements MyBottomLayout.ICallbackListener {

        @Override
        public void click(int id) {
            switch (id) {
                case R.id.homeLayout:
                    myViewPager.setCurrentItem(0);
                    break;
                case R.id.chosenLayout:
                    myViewPager.setCurrentItem(1);
                    break;
                case R.id.searchLayout:
                    myViewPager.setCurrentItem(2);
                    break;
                case R.id.localLayout:
                    myViewPager.setCurrentItem(3);
                    break;
                case R.id.settingLayout:
                    myViewPager.setCurrentItem(4);
                    break;
            }
        }
    }

    /**
     * viewPager的adapter,改变当前fragment
     */
    private class MyFragmentAdapter extends FragmentPagerAdapter {

        public MyFragmentAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    return new HomeFragment();
                case 1:
                    return new ChosenFragment();
                case 2:
                    return new SearchFragment();
                case 3:
                    return new LocalFragment();
                case 4:
                    return new SettingFragment();
            }
            return null;
        }

        @Override
        public int getCount() {
            //一共5个页面
            return 5;
        }
    }

    @Override
    public void progress() {
    }
}

Demo下载地址 使用ViewPager和Fragment实现底部导航滑动重构版

你可能感兴趣的:(Android)