Android 仿微信底部渐变Tab效果

Android 仿微信底部渐变Tab效果,第1张

概述先来看一下效果图除了第三个的发现Tab有所差别外,其他的基本还原了微信的底部Tab渐变效果

先来看一下效果图

除了第三个的发现Tab有所差别外,其他的基本还原了微信的底部Tab渐变效果

每个Tab都是一个自定义view,根据ImageVIEw的tint属性来实现颜色渐变效果,tint属性的使用可以看我的上一篇文章

我将自定义view命名为ShadeVIEw,包含四个自定义属性

意思分别为图标、背景色、底部文本、底部文本大小

  <declare-styleable name="ShadeVIEw">    <attr name="icon" format="reference" />    <attr name="color" format="color" />    <attr name="text" format="string" />    <attr name="text_size" format="dimension" />  </declare-styleable>

ShadeVIEw的定义如下,主要是进行绘图 *** 作,并向外提供改变透明度和图标的方法

public class ShadeVIEw extends VIEw {  /**   * 图标   */  private Bitmap iconBitmap;  /**   * 图标背景色   */  private int iconBackgroundcolor;  /**   * 图标默认背景色   */  private final int DEFAulT_ICON_BACKGROUND_color = 0x3CAF36;  /**   * 图标底部文本   */  private String text;  /**   * 图标底部文字默认大小(sp)   */  private final int DEFAulT_TEXT_SIZE = 12;  /**   * 图标底部文字默认颜色   */  private final int DEFAulT_TEXT_color = 0x2B2B2B;  /**   * 图标绘制范围   */  private Rect iconRect;  /**   * 文字笔画   */  private Paint textPaint;  /**   * 文字范围   */  private Rect textBound;  /**   * 透明度(0.0-1.0)   */  private float mAlpha;  private Bitmap mBitmap;  public ShadeVIEw(Context context,AttributeSet attrs) {    super(context,attrs);    //获取自定义属性值    TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.ShadeVIEw);    BitmapDrawable drawable = (BitmapDrawable) typedArray.getDrawable(R.styleable.ShadeVIEw_icon);    if (drawable != null) {      iconBitmap = drawable.getBitmap();    }    iconBackgroundcolor = typedArray.getcolor(R.styleable.ShadeVIEw_color,DEFAulT_ICON_BACKGROUND_color);    text = typedArray.getString(R.styleable.ShadeVIEw_text);    int textSize = (int) typedArray.getDimension(R.styleable.ShadeVIEw_text_size,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,DEFAulT_TEXT_SIZE,getResources().getdisplayMetrics()));    //资源回收    typedArray.recycle();    //初始化    textBound = new Rect();    textPaint = new Paint();    textPaint.setTextSize(textSize);    textPaint.setcolor(DEFAulT_TEXT_color);    textPaint.setAntiAlias(true);    textPaint.setDither(true);    textPaint.getTextBounds(text,text.length(),textBound);  }  @OverrIDe  protected voID onMeasure(int wIDthMeasureSpec,int heightmeasureSpec) {    super.onMeasure(wIDthMeasureSpec,heightmeasureSpec);    //因为图标是正方形且需要居中显示的,所以VIEw的大小去掉padding和文字所占空间后,    //剩余的空间的宽和高的最小值才是图标的边长    int bitmapSIDe = Math.min(getMeasureDWIDth() - getpaddingleft()        - getpaddingRight(),getMeasuredHeight() - getpaddingtop()        - getpaddingBottom() - textBound.height());    int left = getMeasureDWIDth() / 2 - bitmapSIDe / 2;    int top = (getMeasuredHeight() - textBound.height()) / 2 - bitmapSIDe / 2;    //获取图标的绘制范围    iconRect = new Rect(left,top,left + bitmapSIDe,top + bitmapSIDe);  }  @OverrIDe  protected voID onDraw(Canvas canvas) {    //进一取整    int Alpha = (int) Math.ceil((255 * mAlpha));    //绘制原图标    canvas.drawBitmap(iconBitmap,null,iconRect,null);    setupTargetBitmap(Alpha);    drawSourceText(canvas,Alpha);    drawTargetText(canvas,Alpha);    canvas.drawBitmap(mBitmap,null);  }  /**   * 在mBitmap上绘制以iconBackgroundcolor颜色为Dst,DST_IN模式下的图标   *   * @param Alpha Src颜色的透明度   */  private voID setupTargetBitmap(int Alpha) {    mBitmap = Bitmap.createBitmap(getMeasureDWIDth(),getMeasuredHeight(),Config.ARGB_8888);    Canvas canvas = new Canvas(mBitmap);    Paint paint = new Paint();    paint.setcolor(iconBackgroundcolor);    paint.setAntiAlias(true);    paint.setDither(true);    paint.setAlpha(Alpha);    //在图标背后先绘制一层iconBackgroundcolor颜色的背景    canvas.drawRect(iconRect,paint);    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));    paint.setAlpha(255);    //在mBitmap上绘制以iconBackgroundcolor颜色为Dst,DST_IN模式下的图标    canvas.drawBitmap(iconBitmap,paint);  }  /**   * 绘制默认状态下的字体   *   * @param canvas Canvas   * @param Alpha 字体颜色透明度   */  private voID drawSourceText(Canvas canvas,int Alpha) {    textPaint.setcolor(DEFAulT_TEXT_color);    textPaint.setAlpha(255 - Alpha);    canvas.drawText(text,iconRect.left + iconRect.wIDth() / 2 - textBound.wIDth() / 2,iconRect.bottom + textBound.height(),textPaint);  }  /**   * 绘制滑动到该标签时的字体   *   * @param canvas Canvas   * @param Alpha 字体颜色透明度   */  private voID drawTargetText(Canvas canvas,int Alpha) {    textPaint.setcolor(iconBackgroundcolor);    textPaint.setAlpha(Alpha);    canvas.drawText(text,textPaint);  }  /**   * 设置图标透明度并重绘   *   * @param Alpha 透明度   */  public voID setIconAlpha(float Alpha) {    if (mAlpha != Alpha) {      this.mAlpha = Alpha;      invalIDateVIEw();    }  }  public voID setIconBitmap(Context context,int resourceID) {    BitmapDrawable bitmapDrawable = (BitmapDrawable) ContextCompat.getDrawable(context,resourceID);    if (!bitmapDrawable.getBitmap().equals(iconBitmap)) {      iconBitmap = bitmapDrawable.getBitmap();      invalIDateVIEw();    }  }  /**   * 判断当前是否为UI线程,是则直接重绘,否则调用postInvalIDate()利用Handler来重绘   */  private voID invalIDateVIEw() {    if (Looper.getMainLooper() == Looper.myLooper()) {      invalIDate();    } else {      postInvalIDate();    }  }  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,mAlpha);    return bundle;  }  /**   * 恢复状态   *   * @param parcelable Parcelable   */  @OverrIDe  protected voID onRestoreInstanceState(Parcelable parcelable) {    if (parcelable instanceof Bundle) {      Bundle bundle = (Bundle) parcelable;      mAlpha = bundle.getfloat(STATE_Alpha);      super.onRestoreInstanceState(bundle.getParcelable(STATE_INSTANCE));    } else {      super.onRestoreInstanceState(parcelable);    }  }}

然后在布局文件中声明使用,这里不需要每个自定义属性都使用到,因为我也提供了默认值

<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.v4.vIEw.VIEwPager    androID:ID="@+ID/ID_vIEwpager"    androID:layout_wIDth="match_parent"    androID:layout_height="0dp"    androID:layout_weight="1" />  <linearLayout    androID:layout_wIDth="match_parent"    androID:layout_height="60dp"    androID:background="@drawable/tab_background"    androID:orIEntation="horizontal"    androID:paddingBottom="3dp"    androID:paddingtop="1dp">    <com.example.zy.myapplication.ShadeVIEw      androID:ID="@+ID/ID_indicator_one"      androID:layout_wIDth="0dp"      androID:layout_height="match_parent"      androID:layout_weight="1"      androID:padding="5dp"      app:icon="@drawable/weixin"      app:text="微信" />    <com.example.zy.myapplication.ShadeVIEw      androID:ID="@+ID/ID_indicator_two"      androID:layout_wIDth="0dp"      androID:layout_height="match_parent"      androID:layout_weight="1"      androID:padding="5dp"      app:icon="@drawable/address_book"      app:text="通讯录" />    <com.example.zy.myapplication.ShadeVIEw      androID:ID="@+ID/ID_indicator_three"      androID:layout_wIDth="0dp"      androID:layout_height="match_parent"      androID:layout_weight="1"      androID:padding="5dp"      app:icon="@drawable/discover"      app:text="发现" />    <com.example.zy.myapplication.ShadeVIEw      androID:ID="@+ID/ID_indicator_four"      androID:layout_wIDth="0dp"      androID:layout_height="match_parent"      androID:layout_weight="1"      androID:padding="5dp"      app:icon="@drawable/me"      app:text="我" />  </linearLayout></linearLayout>

因为主界面是VIEwPager,这里就需要一个Fragment子类

public class TabFragment extends Fragment {  @OverrIDe  public VIEw onCreateVIEw(LayoutInflater inflater,VIEwGroup container,Bundle savedInstanceState) {    String mTitle = "微信";    if (getArguments() != null) {      mTitle = getArguments().getString("Title","微信");    }    TextVIEw textVIEw = new TextVIEw(getActivity());    textVIEw.setTextSize(25);    textVIEw.setGravity(Gravity.CENTER);    textVIEw.setText(mTitle);    return textVIEw;  }}

MainActivity代码如下,重点是对vIEwPager进行滑动监听,根据滑动偏移量来动态改变透明度Alpha,从而实现颜色渐变效果

public class MainActivity extends AppCompatActivity implements VIEwPager.OnPagechangelistener,VIEw.OnClickListener {  private List<TabFragment> tabFragments;  private List<ShadeVIEw> tabIndicators;  private VIEwPager vIEwPager;  private FragmentPagerAdapter adapter;  @OverrIDe  protected voID onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentVIEw(R.layout.activity_main);    initData();    vIEwPager = (VIEwPager) findVIEwByID(R.ID.ID_vIEwpager);    vIEwPager.setAdapter(adapter);    vIEwPager.addOnPagechangelistener(this);  }  private voID initData() {    tabFragments = new ArrayList<>();    tabIndicators = new ArrayList<>();    String[] Titles = new String[]{"微信","通讯录","发现","我"};    for (String Title : Titles) {      TabFragment tabFragment = new TabFragment();      Bundle bundle = new Bundle();      bundle.putString("Title",Title);      tabFragment.setArguments(bundle);      tabFragments.add(tabFragment);    }    adapter = new FragmentPagerAdapter(getSupportFragmentManager()) {      @OverrIDe      public int getCount() {        return tabFragments.size();      }      @OverrIDe      public Fragment getItem(int arg0) {        return tabFragments.get(arg0);      }    };    initTabIndicator();  }  private voID initTabIndicator() {    ShadeVIEw one = (ShadeVIEw) findVIEwByID(R.ID.ID_indicator_one);    ShadeVIEw two = (ShadeVIEw) findVIEwByID(R.ID.ID_indicator_two);    ShadeVIEw three = (ShadeVIEw) findVIEwByID(R.ID.ID_indicator_three);    ShadeVIEw four = (ShadeVIEw) findVIEwByID(R.ID.ID_indicator_four);    tabIndicators.add(one);    tabIndicators.add(two);    tabIndicators.add(three);    tabIndicators.add(four);    one.setonClickListener(this);    two.setonClickListener(this);    three.setonClickListener(this);    four.setonClickListener(this);    one.setIconAlpha(1.0f);  }  @OverrIDe  public voID onClick(VIEw v) {    resetTabsstatus();    switch (v.getID()) {      case R.ID.ID_indicator_one:        tabIndicators.get(0).setIconAlpha(1.0f);        vIEwPager.setCurrentItem(0,false);        break;      case R.ID.ID_indicator_two:        tabIndicators.get(1).setIconAlpha(1.0f);        vIEwPager.setCurrentItem(1,false);        break;      case R.ID.ID_indicator_three:        tabIndicators.get(2).setIconAlpha(1.0f);        vIEwPager.setCurrentItem(2,false);        break;      case R.ID.ID_indicator_four:        tabIndicators.get(3).setIconAlpha(1.0f);        vIEwPager.setCurrentItem(3,false);        break;    }  }  /**   * 重置Tab状态   */  private voID resetTabsstatus() {    for (int i = 0; i < tabIndicators.size(); i++) {      tabIndicators.get(i).setIconAlpha(0);    }  }  /**   * 如果是直接点击图标来跳转页面的话,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) {    Log.e("TAG","position==" + position);    Log.e("TAG","positionOffset==" + positionOffset);    Log.e("TAG","positionOffsetPixels==" + positionOffsetPixels);    if (positionOffset > 0) {      ShadeVIEw leftTab = tabIndicators.get(position);      ShadeVIEw rightTab = tabIndicators.get(position + 1);      leftTab.setIconAlpha(1 - positionOffset);      rightTab.setIconAlpha(positionOffset);    }  }  @OverrIDe  public voID onPageSelected(int position) {    if (position == 2) {      tabIndicators.get(position).setIconBitmap(this,R.drawable.discover_green);    } else {      tabIndicators.get(2).setIconBitmap(this,R.drawable.discover);    }  }  @OverrIDe  public voID onPageScrollStateChanged(int state) {  }}

总结

以上所述是小编给大家介绍的AndroID 仿微信底部渐变Tab效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!

总结

以上是内存溢出为你收集整理的Android 仿微信底部渐变Tab效果全部内容,希望文章能够帮你解决Android 仿微信底部渐变Tab效果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1143206.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存