国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android 仿微信底部漸變Tab效果

2019-10-22 18:18:18
字體:
來源:轉載
供稿:網友

先來看一下效果圖

android,微信底部漸變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;  /**   * 圖標底部文字默認大?。╯p)   */  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, 0, 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, 0, 0, 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, null, iconRect, 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, iconRect.left + iconRect.width() / 2 - textBound.width() / 2,        iconRect.bottom + textBound.height(), 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效果,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VEVB武林網網站的支持!


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 海城市| 仁化县| 普兰县| 信阳市| 宁河县| 云浮市| 桓台县| 依兰县| 昭觉县| 伊宁市| 绥中县| 体育| 永年县| 饶阳县| 河间市| 临潭县| 格尔木市| 肇源县| 呼图壁县| 江陵县| 灵寿县| 象州县| 昌黎县| 连平县| 广南县| 彰化市| 长宁区| 定襄县| 香港| 革吉县| 富平县| 张家口市| 宁阳县| 杭州市| 荆州市| 承德市| 富锦市| 青田县| 邓州市| 延川县| 徐闻县|