Android 仿微信底部渐变Tab(2)

之前写过一篇仿微信底部渐变Tab的文章:Android 仿微信底部渐变Tab

是根据ImageView的tint属性来实现颜色渐变效果的,这里再来提供一个新思路,是根据图片的透明度来实现Tab渐变切换,步骤比起之前的方法要简单一些,而且效果会更好

img_3a4faaa7cac142f83c1e57654bb9dcae.gif
好像是效果图?

首先需要准备几张如下这样的照片,这都是我解压微信Apk文件得来的

img_9b81e61bc6d704c1c92c4d72fdeaede2.png
叶应是叶

分别对应的是一张透明色和一张绿色,将两张图片重叠在一起放置,在Fragmnet切换时来改变上下两张图片的透明度,从而实现颜色渐变

首先来定义Tab布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical">

    <FrameLayout
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:layout_marginTop="3dp">

        <ImageView
            android:id="@+id/iv_select_icon"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <ImageView
            android:id="@+id/iv_normal_icon"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </FrameLayout>

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginBottom="3dp">

        <TextView
            android:id="@+id/tv_select_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/tv_normal_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </FrameLayout>

</LinearLayout>


因为Tab文字也要实现颜色渐变,所以除了要两个ImageView外还要两个TextView

在values文件夹下新建一个attrs.xml文件需要用到的属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--滑动颜色渐变Tab-->
    <declare-styleable name="ShadeTabView">
        <attr name="normalIcon" format="reference" />
        <attr name="selectIcon" format="reference" />
        <attr name="tab" format="string" />
        <attr name="textSize" format="dimension" />
        <attr name="normalTextColor" format="color" />
        <attr name="selectTextColor" format="color" />
    </declare-styleable>

</resources>

之后就是自定义View了,步骤与我之前的那篇文章类似

/**
 * 作者: 叶应是叶
 * 时间: 2017/3/4 20:47
 * 描述: 渐变Tab
 */
public class ShadeTabView extends FrameLayout {

    /**
     * 一般状态下的图标
     */
    private ImageView iv_normalIcon;

    /**
     * 选中状态下的图标
     */
    private ImageView iv_selectIcon;

    /**
     * 一般状态下底部 TextView
     */
    private TextView tv_normalLabel;

    /**
     * 选中状态下底部 TextView
     */
    private TextView tv_selectLabel;

    /**
     * 选中状态下的文字颜色
     */
    private int selectTextColor;

    /**
     * 底部文字默认大小(sp)
     */
    private final int DEFAULT_TEXT_SIZE = 6;

    /**
     * 一般状态下底部文字默认颜色
     */
    private final String DEFAULT_NORMAL_TEXT_COLOR = "#989898";

    /**
     * 选中状态下底部文字默认颜色
     */
    private final String DEFAULT_SELECT_TEXT_COLOR = "#45C01A";

    private float alpha;

    public ShadeTabView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);
        //获取自定义属性值
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ShadeTabView, 0, 0);
        BitmapDrawable normalIcon = (BitmapDrawable) typedArray.getDrawable(R.styleable.ShadeTabView_normalIcon);
        BitmapDrawable selectIcon = (BitmapDrawable) typedArray.getDrawable(R.styleable.ShadeTabView_selectIcon);
        String tab = typedArray.getString(R.styleable.ShadeTabView_tab);
        float textSize = typedArray.getDimension(R.styleable.ShadeTabView_textSize,
                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, DEFAULT_TEXT_SIZE, getResources().getDisplayMetrics()));
        int normalTextColor = typedArray.getColor(R.styleable.ShadeTabView_normalTextColor, Color.parseColor(DEFAULT_NORMAL_TEXT_COLOR));
        selectTextColor = typedArray.getColor(R.styleable.ShadeTabView_selectTextColor, Color.parseColor(DEFAULT_SELECT_TEXT_COLOR));
        //资源回收
        typedArray.recycle();
        //属性设置
        iv_normalIcon.setImageDrawable(normalIcon);
        iv_selectIcon.setImageDrawable(selectIcon);
        tv_normalLabel.setText(tab);
        tv_normalLabel.setTextSize(textSize);
        tv_normalLabel.setTextColor(normalTextColor);
        tv_selectLabel.setText(tab);
        tv_selectLabel.setTextSize(textSize);
        tv_selectLabel.setTextColor(selectTextColor);
        setIconAlpha(1);
    }

    private void initView(Context context) {
        LayoutInflater.from(context).inflate(R.layout.view_shade_tab, this);
        iv_normalIcon = (ImageView) findViewById(R.id.iv_normal_icon);
        iv_selectIcon = (ImageView) findViewById(R.id.iv_select_icon);
        tv_normalLabel = (TextView) findViewById(R.id.tv_normal_label);
        tv_selectLabel = (TextView) findViewById(R.id.tv_select_label);
    }

    /**
     * 设置上下两层图片的透明度,alpha 值越小,图片的颜色越倾向于带有颜色的图层
     *
     * @param alpha 透明度
     */
    public void setIconAlpha(float alpha) {
        // setAlpha(float) 0.0f~1.0f 数值越大越不透明
        iv_selectIcon.setAlpha(1 - alpha);
        iv_normalIcon.setAlpha(alpha);
        tv_normalLabel.setAlpha(alpha);
        tv_selectLabel.setAlpha(1 - alpha);
        this.alpha = alpha;
    }

    private static final String STATE_INSTANCE = "STATE_INSTANCE";

    private static final String STATE_ALPHA = "STATE_ALPHA";

    /**
     * 保存状态
     *
     * @return Parcelable
     */
    @Override
    protected Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        bundle.putParcelable(STATE_INSTANCE, super.onSaveInstanceState());
        bundle.putFloat(STATE_ALPHA, alpha);
        return bundle;
    }

    /**
     * 恢复状态
     *
     * @param parcelable Parcelable
     */
    @Override
    protected void onRestoreInstanceState(Parcelable parcelable) {
        Bundle bundle = (Bundle) parcelable;
        super.onRestoreInstanceState(bundle.getParcelable(STATE_INSTANCE));
        setIconAlpha(bundle.getFloat(STATE_ALPHA));
    }

}

之后,到布局中使用ShadeTabView,并将其与ViewPager的滑动关联起来

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/actionBarSize"
        android:background="#393A3F"
        app:title="@string/app_name"
        app:titleTextColor="@android:color/white" />

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="#abc" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#e7f7f4f4"
        android:orientation="horizontal">

        <com.czy.weixintab.ShadeTabView
            android:id="@+id/stv_weiXin"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:normalIcon="@drawable/tab_weixin"
            app:selectIcon="@drawable/tab_weixin_select"
            app:tab="微信" />

        <com.czy.weixintab.ShadeTabView
            android:id="@+id/stv_address_book"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:normalIcon="@drawable/tab_address_list"
            app:selectIcon="@drawable/tab_address_list_select"
            app:tab="通讯录" />

        <com.czy.weixintab.ShadeTabView
            android:id="@+id/stv_discover"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:normalIcon="@drawable/tab_discover"
            app:selectIcon="@drawable/tab_discover_select"
            app:tab="发现" />

        <com.czy.weixintab.ShadeTabView
            android:id="@+id/stv_me"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:normalIcon="@drawable/tab_me"
            app:selectIcon="@drawable/tab_me_select"
            app:tab="我" />

    </LinearLayout>

</LinearLayout>

为ViewPager设置一个滑动监听器,根据ViewPager的滑动偏移量positionOffset来改变ShadeTabView中上下两张图片的透明度

public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener, View.OnClickListener {

    private List<Fragment> tabFragments;

    private List<ShadeTabView> tabIndicators;

    private ViewPager viewPager;

    private FragmentPagerAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();
        viewPager.setAdapter(adapter);
    }

    private void initData() {
        tabFragments = new ArrayList<>();
        tabIndicators = new ArrayList<>();
        TabFragment weiXinFragment = TabFragment.newInstance("微信");
        TabFragment contactsFragment = TabFragment.newInstance("通讯录");
        TabFragment discoverFragment = TabFragment.newInstance("发现");
        TabFragment meFragment = TabFragment.newInstance("我");
        tabFragments.add(weiXinFragment);
        tabFragments.add(contactsFragment);
        tabFragments.add(discoverFragment);
        tabFragments.add(meFragment);
        adapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
            @Override
            public int getCount() {
                return tabFragments.size();
            }

            @Override
            public Fragment getItem(int arg0) {
                return tabFragments.get(arg0);
            }
        };
    }

    private void initView() {
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        viewPager.addOnPageChangeListener(this);
        ShadeTabView stv_weiXin = (ShadeTabView) findViewById(R.id.stv_weiXin);
        ShadeTabView stv_address_book = (ShadeTabView) findViewById(R.id.stv_address_book);
        ShadeTabView stv_discover = (ShadeTabView) findViewById(R.id.stv_discover);
        ShadeTabView stv_me = (ShadeTabView) findViewById(R.id.stv_me);
        tabIndicators.add(stv_weiXin);
        tabIndicators.add(stv_address_book);
        tabIndicators.add(stv_discover);
        tabIndicators.add(stv_me);
        stv_weiXin.setOnClickListener(this);
        stv_address_book.setOnClickListener(this);
        stv_discover.setOnClickListener(this);
        stv_me.setOnClickListener(this);
        stv_weiXin.setIconAlpha(0);
    }

    /**
     * 重置Tab状态
     */
    private void resetTabsStatus() {
        for (int i = 0; i < tabIndicators.size(); i++) {
            tabIndicators.get(i).setIconAlpha(1);
        }
    }

    /**
     * 如果是直接点击图标来跳转页面的话,position值为0到3,positionOffset一直为0.0
     * 如果是通过滑动来跳转页面的话
     * 假如是从第一页滑动到第二页
     * 在这个过程中,positionOffset从接近0逐渐增大到接近1.0,滑动完成后又恢复到0.0,而position只有在滑动完成后才从0变为1
     * 假如是从第二页滑动到第一页
     * 在这个过程中,positionOffset从接近1.0逐渐减小到0.0,而position一直是0
     *
     * @param position             当前页面索引
     * @param positionOffset       偏移量
     * @param positionOffsetPixels 偏移量
     */
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        if (positionOffset > 0) {
            ShadeTabView leftTab = tabIndicators.get(position);
            ShadeTabView rightTab = tabIndicators.get(position + 1);
            leftTab.setIconAlpha(positionOffset);
            rightTab.setIconAlpha(1 - positionOffset);
        }
    }

    @Override
    public void onPageSelected(int position) {

    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }

    @Override
    public void onClick(View v) {
        resetTabsStatus();
        switch (v.getId()) {
            case R.id.stv_weiXin:
                tabIndicators.get(0).setIconAlpha(0);
                viewPager.setCurrentItem(0, false);
                break;
            case R.id.stv_address_book:
                tabIndicators.get(1).setIconAlpha(0);
                viewPager.setCurrentItem(1, false);
                break;
            case R.id.stv_discover:
                tabIndicators.get(2).setIconAlpha(0);
                viewPager.setCurrentItem(2, false);
                break;
            case R.id.stv_me:
                tabIndicators.get(3).setIconAlpha(0);
                viewPager.setCurrentItem(3, false);
                break;
        }
    }

}

这里提供代码下载:Android 仿微信底部渐变Tab(2)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值