美文网首页
撸一个微信的底部Tab切换透明度变化效果

撸一个微信的底部Tab切换透明度变化效果

作者: 熊sir要早睡早起 | 来源:发表于2017-10-15 14:26 被阅读0次

    微信6.0的时候就出现有了底部Tab切换透明度变化的效果,趁着周末也抽空来实现一下,其实十分简单,我们先来看一下效果:

    嗯,没错,又是偷的图

    原图来自:https://img.haomeiwen.com/i2552605/8cf01f84f3a344d3?imageMogr2/auto-orient/strip
    效果大概就跟上图一模一样吧。,所以我就懒得自己录制了。
    首先我们拿到这一个需求,操起我们的笔和纸,将你知道的一些用于实现的思路写下来,要养成一个良好的习惯哦。

    解剖后大概能知道:1,ViewPager和Fragment结合使用(此处用FragmentPagerAdapter)
    2,可能需要两套图,选中状态套餐A(就是那个绿帽子颜色的),未选中时的套餐B(被绿后世界都变成灰色了)
    3,需要动态的获取position以及positionOffset,然后拿到左右两个View,设置positionOffset (这个值时关键!!!);
    4,处理点击时图片文字切换
    哇靠,原来就这么简单。

    那么这里最骚的操作在哪里呢,就是重中之重的第三步操作了!!
    有些同学可能会疑问positionOffset是什么,怎么用?

    这里给大家简单通过一道数学题目来解释一下,我们大家都解过方程式吧,such as:y=1-x;我们画个图,大概长这样:

    y随着x的递增而减小。

    其实我们的滑动处理和这个函数的一模一样的,我们当前选中项的绿色透明度为1,下一个Tab的值为0(Y),positionOffset的值即为X。


    好的,本文分析到此结束!

    同学可以下课自己实现了

    我也偷偷打开我的Android studio实现了一波:

    首先我们看xml代码,我们需要在xml中通过相对布局或者FramLayout来将绿色图套在灰色图之上!!!(因为无论透明度如何发现改变,只是针对绿色图片,我!们!底!部!的!灰!色!图!片!一!直!都!在!)。

    我们每个tab都应该时这样处理的,这里给出一个,另外三个是一样的。文末给出完整代码

               <RelativeLayout android:layout_height="match_parent"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="vertical"
            android:id="@+id/rl_mine"
            android:layout_width="0dp">
    
            <!--正常显示时的图片-->
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:src="@mipmap/mine_normal" />
            <!--选中时的图片-->
            <ImageView
                android:id="@+id/mine"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:src="@mipmap/mine_selected" />
            <!--正常显示的文字颜色-->
            <TextView
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/mine"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:text="我"
                />
            <!--选中时显示的文字颜色-->
            <TextView
                android:textColor="#46c01b"
                android:id="@+id/mine_tv"
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/mine"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:text="我"
                />
        </RelativeLayout>
    
    xml分界线,接下来是Java了

    接下来好戏登场了,我们开始编写Java代码啦。

    首先创建一个TabFragment,大致如下:

    public class TabFragment extends Fragment{
    
    //默认显示文字
    private String content ="default";
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
        /**
         * 通过Arguments获取传来的参数,与getActivity.getIntent.getXXX("xxx")相比,此方式实现了与Activity的解耦
         * 使得我们的TabFragment可以复用。
         */
        if (getArguments()!=null){
            content = getArguments().getString("content");
        }
        
        TextView textView = new TextView(getContext());
        textView.setGravity(Gravity.CENTER);
        textView.setText(content);
        textView.setTextSize(26);
        textView.setBackgroundColor(Color.parseColor("#ffffffff"));
        return textView;
    }}
    

    Fragment创建好了,还是非常简单的,无非就是一个TextView,这里为了方便复用Fragment,不通过编写多套布局的方式一个一个Inflate。

    Activity:

    第一步,findById,这里我是用ButterKnife插件,就不一一find了。
    @BindView(R.id.viewPager)
    ViewPager viewPager;//ViewPager
    @BindView(R.id.home)
    ImageView home;//绿色的微信图片
    @BindView(R.id.home_tv)
    TextView homeTv;//绿色的微信文字
    @BindView(R.id.rl_home)
    RelativeLayout rlHome;
    @BindView(R.id.category)
    ImageView category;//绿色的通讯录图片
    @BindView(R.id.category_tv)
    TextView categoryTv;//绿色的通讯录文字
    @BindView(R.id.rl_category)
    RelativeLayout rlCategory;
    @BindView(R.id.service)
    ImageView service;//绿色的发现图片
    @BindView(R.id.service_tv)
    TextView serviceTv;//绿色的发现文字
    @BindView(R.id.rl_service)
    RelativeLayout rlService;
    @BindView(R.id.mine)
    ImageView mine;//绿色的我图片
    @BindView(R.id.mine_tv)
    TextView mineTv;//绿色的我文字
    @BindView(R.id.rl_mine)
    RelativeLayout rlMine;
    private MyPagerAdapter adapter;//适配器

    private List<Fragment> mTabs = new ArrayList<>();//Fragment集合
    private List<ImageView> images = new ArrayList<>();//绿色图片集合
    private List<TextView> texts = new ArrayList<>();//绿色文字集合
    private String[] mContents = new String[]{"微信", "通讯录", "发现", "我"};//Fragment中TextView显示内容
    

    第二步:初始化数据:

    private void initData() {
    
        //创建TabFragment
        for (int i = 0; i < mContents.length; i++) {
            TabFragment tabFragment = new TabFragment();
            Bundle bundle = new Bundle();
            bundle.putString("content", mContents[i]);
            tabFragment.setArguments(bundle);
            mTabs.add(tabFragment);
        }
        images.add(home);
        images.add(category);
        images.add(service);
        images.add(mine);
    
        texts.add(homeTv);
        texts.add(categoryTv);
        texts.add(serviceTv);
        texts.add(mineTv);
        setselectedTabColor(0);
    }
    

    上面创建了四个TabFragment,并且将我们的绿色图片和绿色文字分别添加到集合中,方便后期做切换处理。

    第三步:编写FragmentPagerAdapter并绑定。

    private class MyPagerAdapter extends FragmentPagerAdapter {
    
        //构造方法
        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }
        //返回当前Fragment
        @Override
        public Fragment getItem(int position) {
            return mTabs.get(position);
        }
    
        //返回Fragment个数
        @Override
        public int getCount() {
            return mTabs.size();
        }
    }
    

    记得在Activity中的onCreate方法中绑定适配器:
    viewPager.setAdapter(adapter = new MyPagerAdapter(getSupportFragmentManager()));
    viewPager.setOnPageChangeListener(this);

    第四步:实现ViewPager的onPagerChangeListener方法
    implements ViewPager.OnPageChangeListener

    第五步:实现底部Tab选中时图片和文字的切换:

    private void setselectedTabColor(int pos) {
    
        images.get(0).setAlpha(0f);
        images.get(1).setAlpha(0f);
        images.get(2).setAlpha(0f);
        images.get(3).setAlpha(0f);
    
        texts.get(0).setAlpha(0f);
        texts.get(1).setAlpha(0f);
        texts.get(2).setAlpha(0f);
        texts.get(3).setAlpha(0f);
        images.get(pos).setAlpha(1f);
        texts.get(pos).setAlpha(1f);
    }
    

    第六步:实现透明度变化方法:

    private void changeAlpha(int pos, float posOffset) {
    
        int nextIndex = pos + 1;
        if (posOffset > 0) {
            //设置tab的颜色渐变效果
            images.get(pos).setAlpha(1f - posOffset);
            images.get(nextIndex).setAlpha(posOffset);
            texts.get(pos).setAlpha(1f-posOffset);
            texts.get(nextIndex).setAlpha(posOffset);
        }
    }
    

    第七步:重写OnPageChangeListener的onPageScrolled,onPageSelected的方法:

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
        changeAlpha(position, positionOffset);
    }
    
    @Override
    public void onPageSelected(int position) {
    
        switch (position) {
            case 0:
                setselectedTabColor(0);
                break;
            case 1:
                setselectedTabColor(1);
                break;
            case 2:
                setselectedTabColor(2);
                break;
            case 3:
                setselectedTabColor(3);
                break;
    
        }
    }
    
    @Override
    public void onPageScrollStateChanged(int state) {
    
    }
    

    最后一步:处理点击事件中Fragment切换和底部Tab切换:

    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.rl_home:
                viewPager.setCurrentItem(0, false);
                setselectedTabColor(0);
                break;
            case R.id.rl_category:
                viewPager.setCurrentItem(1, false);
                setselectedTabColor(1);
                break;
            case R.id.rl_service:
                viewPager.setCurrentItem(2, false);
                setselectedTabColor(2);
                break;
            case R.id.rl_mine:
                viewPager.setCurrentItem(3, false);
                setselectedTabColor(3);
                break;
        }
    }
    

    这里需要注意的时viewPager.setCurrentItem方法,第二个参数为是否启用ViewPager滑动时的动画效果,我们这里因为有透明度的变化,但它只是在滑动时才具有的,点击时不需要,不然会有很糟糕的视觉效果!!!同学可以试一下。

    完成了,喝杯啤酒,兄弟

    这里给出完整代码:
    xml中:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.xjf.wxswitchdemo.MainActivity">
    
    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        tools:layout_editor_absoluteY="0dp"
        tools:layout_editor_absoluteX="8dp"
        ></android.support.v4.view.ViewPager>
    
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#888"
        tools:layout_editor_absoluteY="0dp"
        tools:layout_editor_absoluteX="8dp" />
    
    <LinearLayout
        android:layout_width="match_parent"
        android:gravity="center"
        android:orientation="horizontal"
        android:layout_height="55dp">
    
        <RelativeLayout
            android:id="@+id/rl_home"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="vertical">
    
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:src="@mipmap/home_normal" />
    
            <ImageView
                android:id="@+id/home"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:src="@mipmap/home_selected" />
    
            <TextView
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/home"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:text="微信"
                />
    
            <TextView
                android:textColor="#46c01b"
                android:id="@+id/home_tv"
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/home"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:text="微信"
                />
    
        </RelativeLayout>
    
        <RelativeLayout
            android:id="@+id/rl_category"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="vertical">
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:src="@mipmap/category_normal" />
    
            <ImageView
                android:id="@+id/category"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:src="@mipmap/category_selected" />
    
            <TextView
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/category"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:text="通讯录"
                />
    
            <TextView
                android:textColor="#46c01b"
                android:id="@+id/category_tv"
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/category"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:text="通讯录"
                />
        </RelativeLayout>
    
        <RelativeLayout
            android:id="@+id/rl_service"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="vertical">
    
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:src="@mipmap/service_normal" />
    
            <ImageView
                android:id="@+id/service"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:src="@mipmap/service_selected" />
    
            <TextView
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/service"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:text="发现"
                />
    
            <TextView
                android:textColor="#46c01b"
                android:id="@+id/service_tv"
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/service"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:text="发现"
                />
        </RelativeLayout>
    
        <RelativeLayout
            android:id="@+id/rl_mine"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="vertical">
    
            <!--正常显示时的图片-->
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:src="@mipmap/mine_normal" />
            <!--选中时的图片-->
            <ImageView
                android:id="@+id/mine"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:src="@mipmap/mine_selected" />
            <!--正常显示的文字颜色-->
            <TextView
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/mine"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:text="我"
                />
            <!--选中时显示的文字颜色-->
            <TextView
                android:textColor="#46c01b"
                android:id="@+id/mine_tv"
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/mine"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:text="我"
                />
        </RelativeLayout>
    
    </LinearLayout></LinearLayout>
    

    MainActivity中代码:

    public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {
    
    
    @BindView(R.id.viewPager)
    ViewPager viewPager;//ViewPager
    @BindView(R.id.home)
    ImageView home;//绿色的微信图片
    @BindView(R.id.home_tv)
    TextView homeTv;//绿色的微信问题
    @BindView(R.id.rl_home)
    RelativeLayout rlHome;
    @BindView(R.id.category)
    ImageView category;//绿色的通讯录图片
    @BindView(R.id.category_tv)
    TextView categoryTv;//绿色的通讯录文字
    @BindView(R.id.rl_category)
    RelativeLayout rlCategory;
    @BindView(R.id.service)
    ImageView service;//绿色的发现图片
    @BindView(R.id.service_tv)
    TextView serviceTv;//绿色的发现文字
    @BindView(R.id.rl_service)
    RelativeLayout rlService;
    @BindView(R.id.mine)
    ImageView mine;//绿色的我图片
    @BindView(R.id.mine_tv)
    TextView mineTv;//绿色的我文字
    @BindView(R.id.rl_mine)
    RelativeLayout rlMine;
    private MyPagerAdapter adapter;//适配器
    
    private List<Fragment> mTabs = new ArrayList<>();//Fragment集合
    private List<ImageView> images = new ArrayList<>();//绿色图片集合
    private List<TextView> texts = new ArrayList<>();//绿色文字集合
    private String[] mContents = new String[]{"微信", "通讯录", "发现", "我"};//Fragment中TextView显示内容
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        initData();
        viewPager.setAdapter(adapter = new MyPagerAdapter(getSupportFragmentManager()));
        viewPager.setOnPageChangeListener(this);
    }
    
    private void initData() {
        //创建TabFragment
        for (int i = 0; i < mContents.length; i++) {
            TabFragment tabFragment = new TabFragment();
            Bundle bundle = new Bundle();
            bundle.putString("content", mContents[i]);
            tabFragment.setArguments(bundle);
            mTabs.add(tabFragment);
        }
        images.add(home);
        images.add(category);
        images.add(service);
        images.add(mine);
    
        texts.add(homeTv);
        texts.add(categoryTv);
        texts.add(serviceTv);
        texts.add(mineTv);
        setselectedTabColor(0);
    }
    
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
        changeAlpha(position, positionOffset);
    }
    
    @Override
    public void onPageSelected(int position) {
    
        switch (position) {
            case 0:
                setselectedTabColor(0);
                break;
            case 1:
                setselectedTabColor(1);
                break;
            case 2:
                setselectedTabColor(2);
                break;
            case 3:
                setselectedTabColor(3);
                break;
    
        }
    }
    
    @Override
    public void onPageScrollStateChanged(int state) {
    
    }
    
    
    private void changeAlpha(int pos, float posOffset) {
    
        int nextIndex = pos + 1;
        if (posOffset > 0) {
            //设置tab的颜色渐变效果
            images.get(pos).setAlpha(1f - posOffset);
            images.get(nextIndex).setAlpha(posOffset);
            texts.get(pos).setAlpha(1f-posOffset);
            texts.get(nextIndex).setAlpha(posOffset);
        }
    }
    
    ;
    
    
    private void setselectedTabColor(int pos) {
    
        images.get(0).setAlpha(0f);
        images.get(1).setAlpha(0f);
        images.get(2).setAlpha(0f);
        images.get(3).setAlpha(0f);
    
        texts.get(0).setAlpha(0f);
        texts.get(1).setAlpha(0f);
        texts.get(2).setAlpha(0f);
        texts.get(3).setAlpha(0f);
        images.get(pos).setAlpha(1f);
        texts.get(pos).setAlpha(1f);
    }
    
    private class MyPagerAdapter extends FragmentPagerAdapter {
    
        //构造方法
        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }
        //返回当前Fragment
        @Override
        public Fragment getItem(int position) {
            return mTabs.get(position);
        }
    
        //返回Fragment个数
        @Override
        public int getCount() {
            return mTabs.size();
        }
    }
    
    @OnClick({R.id.rl_home, R.id.rl_category, R.id.rl_service, R.id.rl_mine})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.rl_home:
                viewPager.setCurrentItem(0, false);
                setselectedTabColor(0);
                break;
            case R.id.rl_category:
                viewPager.setCurrentItem(1, false);
                setselectedTabColor(1);
                break;
            case R.id.rl_service:
                viewPager.setCurrentItem(2, false);
                setselectedTabColor(2);
                break;
            case R.id.rl_mine:
                viewPager.setCurrentItem(3, false);
                setselectedTabColor(3);
                break;
        }
    }}
    

    你以为这样就结束了吗?不是这样的,装逼还没有结束。


    接下来我们自定义一个透明度自动变化的Tab容器控件!!!没错,其实思路和之前类似,只不过是自定义控件而已。那么我们就直接开始干了!!!!!!!!!!!!!

    首先是定义一个透明度可以改变的ImageView;

    public class TabIconView extends ImageView{
    
    private Paint mPaint;
    //选中时bitmap
    private Bitmap mSelectedIcon;
    //正常状态下bitmap
    private Bitmap mNormalIcon;
    
    //focus bitmap矩阵
    private Rect mSelectedRect;
    // normal bitmap矩阵
    private Rect mNormalRect;
    /** 当前选择项(mSelectedIcon)透明度
     * mNormalIcon透明度即为 255 - mSelectedAlpha*/
    private int mSelectedAlpha = 0;
    
    public TabIconView(Context context) {
        this(context,null);
    }
    
    public TabIconView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }
    
    public TabIconView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    
    /**
     * 初始化资源图片bitmap及相关绘制对象
     * @param normal
     * @param selected
     * @param width
     * @param height
     */
    public final void init(int normal,int selected,int width,int height){
        this.mNormalIcon = BitmapFactory.decodeResource(getResources(),normal);
        this.mSelectedIcon = BitmapFactory.decodeResource(getResources(),selected);
        this.mNormalRect = new Rect(0,0,width,height);
        this.mSelectedRect = new Rect(0,0,width,height);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//设置画笔抗锯齿
    };
    
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mPaint==null){
            return;
        }
        mPaint.setAlpha(255-this.mSelectedAlpha);
        canvas.drawBitmap(mNormalIcon,null,mNormalRect,mPaint);
        mPaint.setAlpha(mSelectedAlpha);
        canvas.drawBitmap(mSelectedIcon,null,mSelectedRect,mPaint);
    }
    
    /**
     * 改变透明度
     * @param alpha
     */
    public final void changeSelectedAlpha(int alpha){
        mSelectedAlpha = alpha;
        invalidate();
    }
    
    
    /**
     * 改变透明度百分比
     * @param offset 百分比
     */
    public final void offsetChanged(float offset) {
        changeSelectedAlpha((int) (255 * (1 - offset)));
    }}
    

    接下来撸一个Tab容器。

    public class TabContainerView extends LinearLayout {
    
    private ViewPager mViewPager;
    private ViewPager.OnPageChangeListener mViewPagerPageChangeListener;
    
    /** 默认颜色*/
    private int mTextNormalColor;
    /** 选中时颜色值*/
    private int mTextSelectedColor;
    
    /** 前一次选择位置*/
    private int mLastPosition;
    /** 当前选中位置*/
    private int mSelectedPosition;
    /**选择偏移位置 */
    private float mSelectionOffset;
    
    /** tab 标题*/
    private String[] mTitles;
    /** tab icon集合*/
    private int[][] mIconRes;
    
    /** tab item 视图集合*/
    private View[] mTabView;
    
    /** 布局文件id*/
    private int mLayoutId;
    /** textView 控件id*/
    private int mTextViewId;
    /** icon 控件id*/
    private int mIconVIewId;
    
    /**icon宽度*/
    private int mIconWidth;
    /**icon高度*/
    private int mIconHeight;
    
    /** 是否显示过渡颜色效果*/
    private boolean mShowTransitionColor = true;
    
    public TabContainerView(Context context) {
        this(context, null);
    }
    
    public TabContainerView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    public void initContainer (String[] titles, int[][] iconsRes, int[] colors, boolean showTransitionColor) {
        this.mTitles = titles;
        this.mIconRes = iconsRes;
        this.mTextNormalColor = getResources().getColor(colors[0]);
        this.mTextSelectedColor = getResources().getColor(colors[1]);
        this.mShowTransitionColor = showTransitionColor;
    }
    
    /**
     * 设置布局文件及相关控件id
     * @param layout layout布局文件 id
     * @param iconId ImageView 控件 id id <=0 时不显示
     * @param textId TextView 控件 id id <=0 时不显示
     * @param width  icon 宽度
     * @param height icon 高度
     */
    public void setContainerLayout (int layout, int iconId, int textId, int width, int height) {
        mLayoutId = layout;
        mTextViewId = textId;
        mIconVIewId = iconId;
        mIconWidth = width;
        mIconHeight = height;
    }
    
    /**
     * <p>设置布局文件及相关控件id --只有文本</p>
     * @param layout layout布局文件 id
     * @param textId TextView 控件 id
     * @param width  icon 宽度
     * @param height icon 高度
     */
    public void setSingleTextLayout (int layout, int textId, int width, int height) {
        setContainerLayout(layout, 0, textId, width, height);
    
    }
    
    /**
     * <p>设置布局文件及相关控件id</p>
     * @param layout layout布局文件 id
     * @param iconId ImageView 控件 id
     * @param width  icon 宽度
     * @param height icon 高度
     */
    public void setSingleIconLayout (int layout, int iconId, int width, int height) {
        setContainerLayout(layout, iconId, 0, width,  height);
    }
    
    public void setViewPager(ViewPager viewPager) {
        removeAllViews();
        mViewPager = viewPager;
        if (viewPager != null && viewPager.getAdapter() != null) {
            viewPager.addOnPageChangeListener(new InternalViewPagerListener());
            addTabViewToContainer();
        }
    }
    
    /**
     * <p>添加tab view到当前容器</p>
     */
    private void addTabViewToContainer() {
        final PagerAdapter adapter = mViewPager.getAdapter();
        mTabView = new View[adapter.getCount()];
    
        for (int index = 0, len = adapter.getCount(); index < len; index++) {
    
            final View tabView = LayoutInflater.from(getContext()).inflate(mLayoutId, this, false);
            mTabView[index] = tabView;
    
            /*tabIconView初始化*/
            TabIconView iconView = null;
            if (mIconVIewId > 0) {
                iconView = (TabIconView) tabView.findViewById(mIconVIewId);
                iconView.init(mIconRes[index][0], mIconRes[index][1], mIconWidth, mIconHeight);
            }
    
            /*tabTextView初始化*/
            TextView textView = null;
            if (mTextViewId > 0) {
                textView = (TextView) tabView.findViewById(mTextViewId);
                textView.setText(mTitles[index]);
    
            }
    
            /*设置宽度,等分container*/
            LayoutParams lp = (LayoutParams) tabView.getLayoutParams();
            lp.width = 0;
            lp.weight = 1;
    
            /*添加tab点击事件*/
            addTabOnClickListener(tabView, index);
    
            /*设置当前状态*/
            if (index == mViewPager.getCurrentItem()) {
                if (iconView != null) {
                    iconView.offsetChanged(0);
                }
                tabView.setSelected(true);
                if (textView != null) {
                    textView.setTextColor(mTextSelectedColor);
                }
            }
    
            addView(tabView);
        }
    }
    
    /**
     * <p>viewPager滑动改变监听事件</p>
     */
    private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {
        private int mScrollState;
    
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            onViewPagerPageChanged(position, positionOffset);
    
            if (mViewPagerPageChangeListener != null) {
                mViewPagerPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
            }
        }
    
        @Override
        public void onPageSelected(int position) {
    
            /*完成滑动动作后更新每个Item TextView的颜色值以及ImageView的状态值*/
            for (int i = 0; i < getChildCount(); i++) {
                if (mIconVIewId > 0) {
                    ((TabIconView) mTabView[i].findViewById(mIconVIewId)) .offsetChanged(position == i ? 0 : 1);
                }
                if (mTextViewId > 0) {
                    ((TextView) mTabView[i].findViewById(mTextViewId)) .setTextColor(position == i ? mTextSelectedColor : mTextNormalColor);
                }
            }
    
            if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
                onViewPagerPageChanged(position, 0f);
            }
    
            for (int i = 0, size = getChildCount(); i < size; i++) {
                getChildAt(i).setSelected(position == i);
            }
    
    
            if (mViewPagerPageChangeListener != null) {
                mViewPagerPageChangeListener.onPageSelected(position);
            }
        }
    
        @Override
        public void onPageScrollStateChanged(int state) {
            mScrollState = state;
    
            if (mViewPagerPageChangeListener != null) {
                mViewPagerPageChangeListener.onPageScrollStateChanged(state);
            }
        }
    }
    
    /**
     * viewpager滑动改变后更新当前container视图
     * @param position 当前选择position
     * @param positionOffset position 偏移量
     */
    private void onViewPagerPageChanged(int position, float positionOffset) {
        mSelectedPosition = position;
        mSelectionOffset = positionOffset;
        if (positionOffset == 0f && mLastPosition != mSelectedPosition) {
            mLastPosition = mSelectedPosition;
        }
        invalidate();
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        final int childCount = getChildCount();
        if (childCount > 0) {
            /*当发生偏移时,绘制渐变区域*/
            if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1) && mShowTransitionColor) {
    
                /*获取当前tab和下一tab view */
                View selectedTab = getChildAt(mSelectedPosition);
                View nextTab = getChildAt(mSelectedPosition + 1);
    
                /*显示tab icon时,刷新各自view 透明度*/
                if (mIconVIewId > 0) {
                    View selectedIconView = selectedTab.findViewById(mIconVIewId);
                    View nextIconView = nextTab.findViewById(mIconVIewId);
    
                    //draw icon alpha
                    if (selectedIconView instanceof TabIconView && nextIconView instanceof TabIconView) {
                        ((TabIconView) selectedIconView).offsetChanged(mSelectionOffset);
                        ((TabIconView) nextIconView).offsetChanged(1 - mSelectionOffset);
                    }
                }
    
                 /*显示tab text,刷新各自view 透明度*/
                if  (mTextViewId > 0) {
                    View selectedTextView = selectedTab.findViewById(mTextViewId);
                    View nextTextView = nextTab.findViewById(mTextViewId);
    
                    //draw text color
                    Integer selectedColor = (Integer) evaluate(mSelectionOffset, mTextSelectedColor, mTextNormalColor);
                    Integer nextColor = (Integer) evaluate(1 - mSelectionOffset, mTextSelectedColor, mTextNormalColor);
    
                    if (selectedTextView instanceof TextView && nextTextView instanceof TextView) {
                        ((TextView) selectedTextView).setTextColor(selectedColor);
                        ((TextView) nextTextView).setTextColor(nextColor);
                    }
                }
    
            }
        }
    }
    
    /**
     * tab item点击事件,点击时直接跳到对应view
     * @param view        View
     * @param position position
     */
    private void addTabOnClickListener (View view, final int position) {
        OnClickListener listener = new OnClickListener() {
            @Override
            public void onClick(View v) {
                mViewPager.setCurrentItem(position, false);
            }
        };
        view.setOnClickListener(listener);
    }
    
    
    public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
        mViewPagerPageChangeListener = listener;
    }
    
    /**
     * This function returns the calculated in-between value for a color
     * given integers that represent the start and end values in the four
     * bytes of the 32-bit int. Each channel is separately linearly interpolated
     * and the resulting calculated values are recombined into the return value.
     *
     * @param fraction The fraction from the starting to the ending values
     * @param startValue A 32-bit int value representing colors in the
     * separate bytes of the parameter
     * @param endValue A 32-bit int value representing colors in the
     * separate bytes of the parameter
     * @return A value that is calculated to be the linearly interpolated
     * result, derived by separating the start and end values into separate
     * color channels and interpolating each one separately, recombining the
     * resulting values in the same way.
     */
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        int startInt = (Integer) startValue;
        int startA = (startInt >> 24) & 0xff;
        int startR = (startInt >> 16) & 0xff;
        int startG = (startInt >> 8) & 0xff;
        int startB = startInt & 0xff;
    
        int endInt = (Integer) endValue;
        int endA = (endInt >> 24) & 0xff;
        int endR = (endInt >> 16) & 0xff;
        int endG = (endInt >> 8) & 0xff;
        int endB = endInt & 0xff;
    
        return (startA + (int)(fraction * (endA - startA))) << 24 |
                (startR + (int)(fraction * (endR - startR))) << 16 |
                (startG + (int)(fraction * (endG - startG))) << 8 |
                (startB + (int)(fraction * (endB - startB)));
    }
    
    public int getTextSelectedColor() {
        return mTextSelectedColor;
    }
    
    public void setTextSelectedColor(int textSelectedColor) {
        mTextSelectedColor = textSelectedColor;
    }
    
    public int getTextNormalColor() {
        return mTextNormalColor;
    }
    
    public void setTextNormalColor(int textNormalColor) {
        mTextNormalColor = textNormalColor;
    }
    
    public int getLastPosition() {
        return mLastPosition;
    }
    
    public void setLastPosition(int lastPosition) {
        mLastPosition = lastPosition;
    }
    
    public int getSelectedPosition() {
        return mSelectedPosition;
    }
    
    public void setSelectedPosition(int selectedPosition) {
        mSelectedPosition = selectedPosition;
    }
    
    public float getSelectionOffset() {
        return mSelectionOffset;
    }
    
    public void setSelectionOffset(float selectionOffset) {
        mSelectionOffset = selectionOffset;
    }
    
    public String[] getTitles() {
        return mTitles;
    }
    
    public void setTitles(String[] titles) {
        mTitles = titles;
    }
    
    public int[][] getIconRes() {
        return mIconRes;
    }
    
    public void setIconRes(int[][] iconRes) {
        mIconRes = iconRes;
    }
    
    public View[] getTabView() {
        return mTabView;
    }
    
    public void setTabView(View[] tabView) {
        mTabView = tabView;
    }
    
    public boolean isShowTransitionColor() {
        return mShowTransitionColor;
    }
    
    public void setShowTransitionColor(boolean showTransitionColor) {
        mShowTransitionColor = showTransitionColor;
    }}
    

    卧槽,不知不觉撸了这么多了,不过也完成了,接下来我们就直接拿着用好了。

    首先我们编写一个tab_container_view:

     <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="@null">
    
    <com.example.xjf.wxswitchdemo.TabIconView
        android:id="@+id/iv_tab_icon"
        android:layout_marginTop="3dp"
        android:layout_width="@dimen/tab_icon_width"
        android:layout_height="@dimen/tab_icon_height"
        android:layout_centerHorizontal="true"
        android:scaleType="centerInside" />
    
    <TextView
        android:id="@+id/tv_tab_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:layout_centerHorizontal="true"
        android:layout_below="@+id/iv_tab_icon"
        android:textColor="@color/main_bottom_tab_textcolor_normal"
        /></RelativeLayout>
    

    接下来就是activity的xml了,也比较简单,直接引用我们自定义的TabContainerView就好了

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <android.support.v4.view.ViewPager
        android:id="@+id/tab_pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:overScrollMode="never" />
    
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="#999999"></View>
    
    <com.example.xjf.wxswitchdemo.TabContainerView
        android:id="@+id/ll_tab_container"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@android:color/white" /></LinearLayout>
    

    最后再我们的Activity中完成数据的初始化操作和简单的切换即可。

    public class Activity_Two extends AppCompatActivity implements ViewPager.OnPageChangeListener{
    
    @BindView(R.id.tab_pager)
    ViewPager tabPager;
    @BindView(R.id.ll_tab_container)
    TabContainerView llTabContainer;
    
    private List<Fragment> mTabs = new ArrayList<>();//Fragment集合
    private MyPagerAdapter adapter;//适配器
    
    
    private final int ICONS_RES[][] = {
            {
                    R.mipmap.home_normal,
                    R.mipmap.home_selected
            },
            {
                    R.mipmap.category_normal,
                    R.mipmap.category_selected
            },
    
            {
                    R.mipmap.service_normal,
                    R.mipmap.service_selected
            },
            {
                    R.mipmap.mine_normal,
                    R.mipmap.mine_selected
            }
    };
    
    /** tab 颜色值*/
    private final int[] TAB_COLORS = new int []{
            R.color.main_bottom_tab_textcolor_normal,
            R.color.main_bottom_tab_textcolor_selected};
    
    private String[] mContents = new String[]{"微信", "通讯录", "发现", "我"};
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_);
        ButterKnife.bind(this);
        initView();
    }
    
    
    private void initView(){
    
        for (int i = 0; i < mContents.length; i++) {
            TabFragment tabFragment = new TabFragment();
            Bundle bundle = new Bundle();
            bundle.putString("content", mContents[i]);
            tabFragment.setArguments(bundle);
            mTabs.add(tabFragment);
        }
        tabPager.setAdapter(adapter = new MyPagerAdapter(getSupportFragmentManager()));
    
        TabContainerView mTabLayout = (TabContainerView) findViewById(R.id.ll_tab_container);
        mTabLayout.setOnPageChangeListener(this);
        mTabLayout.initContainer(mContents, ICONS_RES, TAB_COLORS, true);
        int width = getResources().getDimensionPixelSize(R.dimen.tab_icon_width);
        int height = getResources().getDimensionPixelSize(R.dimen.tab_icon_height);
        mTabLayout.setContainerLayout(R.layout.tab_container_view, R.id.iv_tab_icon, R.id.tv_tab_text, width, height);
        mTabLayout.setViewPager(tabPager);
        tabPager.setCurrentItem(0);
    }
    
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
    }
    
    @Override
    public void onPageSelected(int position) {
        for (int index = 0, len = mTabs.size(); index < len; index ++) {
            mTabs.get(position).onHiddenChanged(index != position);
        }
    }
    
    @Override
    public void onPageScrollStateChanged(int state) {
    
    }
    
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
    }
    
    private class MyPagerAdapter extends FragmentPagerAdapter {
    
        //构造方法
        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }
        //返回当前Fragment
        @Override
        public Fragment getItem(int position) {
            return mTabs.get(position);
        }
    
        //返回Fragment个数
        @Override
        public int getCount() {
            return mTabs.size();
        }
    }}
    
    到此结束

    图片资源共享一下:

    mine_selected.png
    service_selected.png
    category_selected.png
    category_normal.png
    home_normal.png
    home_selected.png
    mine_normal.png

    各位下期再见!!!!!

    最后录制一张自己实现的效果图吧:

    相关文章

      网友评论

          本文标题:撸一个微信的底部Tab切换透明度变化效果

          本文链接:https://www.haomeiwen.com/subject/xcaquxtx.html