最简单的底部导航栏,仿微信的滑动切换效果

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_39397471/article/details/76614625

最终实现效果:




大体思路:

1. 主要使用两个自定义View配合实现; 底部图标加文字为一个自定义view,底部导航栏为一个载体,根据需要来添加底部图标;
2. 底部导航栏的设置方法类似于TabLayout的关联,View需要创建关联方法,用来关联VIewPager;
3. 通过关联方法获取ViewPager实例后,根据ViewPager页面数创建底部导航栏的图标按钮;

代码实现:

1. 新建第一个自定义View, 图标 + 文字 的底部按钮;

/**
 * 自定义控件,该控件为底部导航栏中的图标
 * Created by MrZheng on 2017/8/2.
 */

public class TabView extends LinearLayout {
    BotBean mBean;
    private TextView title;
    private ImageView iconImage;


    /**
     * 引用此控件,只能通过new 方法;接收一个TabView
     * @param context
     */
    public TabView(Context context, BotBean bean) {
        super(context);
        this.mBean = bean;
        initView();
    }

    /**
     * 初始化布局
     */
    public void initView() {
        setOrientation(VERTICAL);
        setGravity(Gravity.CENTER);

        //添加小图标
        iconImage = new ImageView(getContext());
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT
                , ViewGroup.LayoutParams.WRAP_CONTENT);
        iconImage.setLayoutParams(layoutParams);
        iconImage.setImageResource(mBean.getUncheckedId());

        Drawable drawable = getContext().getResources().getDrawable(mBean.getUncheckedId());
        Drawable wrapDrawable = DrawableCompat.wrap(drawable);
        DrawableCompat.setTintList(wrapDrawable, ColorStateList.valueOf(Color.BLACK));
        iconImage.setImageDrawable(wrapDrawable);

        addView(iconImage);

        //标题
        title = new TextView(getContext());
        LinearLayout.LayoutParams titleParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT);
        title.setLayoutParams(titleParams);
        title.setText(mBean.getContent());
        addView(title);
    }

    //判断选择状态,改变图标
    //供外部调用
    public void setSelected(boolean isSelected) {
        if (mBean == null) {
            return;
        }
        if (isSelected) {
            if (iconImage != null) {
                //使用颜色过滤器,改变选中时的颜色
                Drawable drawable = getContext().getResources().getDrawable(mBean.getUncheckedId());
                Drawable wrapDrawable = DrawableCompat.wrap(drawable);
                DrawableCompat.setTintList(wrapDrawable, ColorStateList.valueOf(Color.GREEN));
                iconImage.setImageDrawable(wrapDrawable);

                title.setTextColor(Color.GREEN);
            }
        } else {
            if (title != null) {
//                iconImage.setImageResource(mBean.getUncheckedId());
                Drawable drawable = getContext().getResources().getDrawable(mBean.getUncheckedId());
                Drawable wrapDrawable = DrawableCompat.wrap(drawable);
                DrawableCompat.setTintList(wrapDrawable, ColorStateList.valueOf(Color.BLACK));
                iconImage.setImageDrawable(wrapDrawable);

                title.setTextColor(Color.GRAY);
            }
        }
    }
}


2. 创建第二个自定义View,该View为底部导航栏载体,根据 关联的ViewPager页面 个数创建 底部导航栏图标;

/**
 * 该控件为底部导航栏图标载体
 * Created by MrZheng on 2017/8/2.
 */

public class bottomView extends LinearLayout {

    private ViewPager vp;
    BottomPageChangeListener mBottomPageChangeListener;


    public bottomView(Context context) {
        super(context);
    }
    public bottomView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    public bottomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * 同TabLayout用法相似,需要与ViewPager进行绑定
     */
    public void setViewPager(ViewPager viewPager, ArrayList<BotBean> botBeen,BottomPageChangeListener bottomPageChangeListener) {
        if (viewPager == null) {
            return;
        }
        vp = viewPager;
        mBottomPageChangeListener = bottomPageChangeListener;
        initTabView(botBeen);

        //设置ViewPager的点击事件
        vp.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
            @Override
            public void onPageSelected(int position) {
                for (int i = 0; i < getChildCount(); i++) {
                    getChildAt(i).setSelected((position == i ? true : false));
                }
                if (mBottomPageChangeListener != null) {
                    mBottomPageChangeListener.onPageChangeListener(position);
                }
            }
        });
    }

    /**
     * 初始化底部导航栏,ViewPager有多少页,就创建多少个图标
     */
    public void initTabView(ArrayList<BotBean> botBeen) {
        setGravity(HORIZONTAL);
        for (int i = 0; i < botBeen.size(); i++) {
            BotBean bean = botBeen.get(i);
            TabView tabView = new TabView(getContext(), bean);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT
                    , ViewGroup.LayoutParams.WRAP_CONTENT);
            params.weight = 1;
            params.gravity = Gravity.CENTER;
            tabView.setLayoutParams(params);

            //为每个view设置点击事件,点击跳转过去
            final int finalI = i;
            tabView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    vp.setCurrentItem(finalI);
                }
            });
            //设置一开始选中状态
            if (i == 0) {
                tabView.setSelected(true);
                //由于初始化时,onPageSelected()选中方法并没有的到执行,所以主动去调用回调方法
                if (mBottomPageChangeListener != null) {
                    mBottomPageChangeListener.onPageChangeListener(i);
                }
            }
            addView(tabView);
        }
    }


    /**
     * 提供接口回调方法,每次滑动都通知外界
     */
    public interface BottomPageChangeListener{
        void onPageChangeListener(int position);
    }
}


3. 添加 图标自定义类, 该类封装着底部导航栏中每一个选项的的图标和文字,将该类型对象添加到集合中,用于给底部导航栏设置图标;

/**
 * 底部导航栏的封装类,该类对象用于在底部导航栏添加对应图标和文字
 * Created by MrZheng on 2017/8/2.
 */

public class BotBean {
    String content;//图标名字
    int uncheckedId;//未选中时的图标

    public BotBean(String content, int uncheckedId) {
        this.content = content;
        this.uncheckedId = uncheckedId;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public int getUncheckedId() {
        return uncheckedId;
    }

    public void setUncheckedId(int uncheckedId) {
        this.uncheckedId = uncheckedId;
    }
}


自定义View实现完成,在Fragment或Activity中使用该View:

1. 在布局文件中添加:

<zhengyanze.com.bottomdemo.widget.bottomView
        android:id="@+id/bottom"
        android:layout_width="match_parent"
        android:layout_height="60dp">
    </zhengyanze.com.bottomdemo.widget.bottomView>

2. 在活动或碎片中添加:

public class MainActivity extends AppCompatActivity {
    ArrayList<Fragment> mFragments;
    ArrayList<BotBean> mItemIcon;//存放底部图标和文字
    private TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mFragments = new ArrayList<>();
        mItemIcon = new ArrayList<>();

        mFragments.add(new TextFragment());
        mFragments.add(new TextFragment());
        mFragments.add(new TextFragment());
        mFragments.add(new TextFragment());
        mItemIcon.add(new BotBean("首页", R.mipmap.ic_home2));
        mItemIcon.add(new BotBean("通讯录", R.mipmap.ic_study2));
        mItemIcon.add(new BotBean("发现", R.mipmap.ic_found2));
        mItemIcon.add(new BotBean("我的", R.mipmap.ic_me2));

        ViewPager vp = (ViewPager) findViewById(R.id.vp);
        vp.setAdapter(new FAdapter(getSupportFragmentManager()));

        tv = (TextView) findViewById(R.id.tv);

        bottomView bottom = (bottomView) findViewById(R.id.bottom);
        bottom.setViewPager(vp, mItemIcon, new bottomView.BottomPageChangeListener() {
            @Override
            public void onPageChangeListener(int position) {
                //滑动后的回调
                tv.setText(mItemIcon.get(position).getContent());
            }
        });
    }

    /**
     * 适配器
     */
    class FAdapter extends FragmentPagerAdapter {
        public FAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragments.get(position);
        }
        @Override
        public int getCount() {
            return mFragments.size();
        }
    }
}



总结:该代码耦合度较高,有些代码可能不太合理;欢迎大牛们给出合理建议;






猜你喜欢

转载自blog.csdn.net/weixin_39397471/article/details/76614625