Android中怎么實(shí)現(xiàn)微信底部漸變Tab效果

本篇文章為大家展示了Android 中怎么實(shí)現(xiàn)微信底部漸變Tab效果,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于做網(wǎng)站、成都網(wǎng)站制作、定西網(wǎng)絡(luò)推廣、小程序開發(fā)、定西網(wǎng)絡(luò)營(yíng)銷、定西企業(yè)策劃、定西品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供定西建站搭建服務(wù),24小時(shí)服務(wù)熱線:028-86922220,官方網(wǎng)址:bm7419.com

將自定義View命名為ShadeView,包含四個(gè)自定義屬性

意思分別為圖標(biāo)、背景色、底部文本、底部文本大小

  <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的定義如下,主要是進(jìn)行繪圖操作,并向外提供改變透明度和圖標(biāo)的方法

public class ShadeView extends View {
  /**
   * 圖標(biāo)
   */
  private Bitmap iconBitmap;
  /**
   * 圖標(biāo)背景色
   */
  private int iconBackgroundColor;
  /**
   * 圖標(biāo)默認(rèn)背景色
   */
  private final int DEFAULT_ICON_BACKGROUND_COLOR = 0x3CAF36;
  /**
   * 圖標(biāo)底部文本
   */
  private String text;
  /**
   * 圖標(biāo)底部文字默認(rèn)大?。╯p)
   */
  private final int DEFAULT_TEXT_SIZE = 12;
  /**
   * 圖標(biāo)底部文字默認(rèn)顏色
   */
  private final int DEFAULT_TEXT_COLOR = 0x2B2B2B;
  /**
   * 圖標(biāo)繪制范圍
   */
  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);
    //因?yàn)閳D標(biāo)是正方形且需要居中顯示的,所以View的大小去掉padding和文字所占空間后,
    //剩余的空間的寬和高的最小值才是圖標(biāo)的邊長(zhǎng)
    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;
    //獲取圖標(biāo)的繪制范圍
    iconRect = new Rect(left, top, left + bitmapSide, top + bitmapSide);
  }
  @Override
  protected void onDraw(Canvas canvas) {
    //進(jìn)一取整
    int alpha = (int) Math.ceil((255 * mAlpha));
    //繪制原圖標(biāo)
    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模式下的圖標(biāo)
   *
   * @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);
    //在圖標(biāo)背后先繪制一層iconBackgroundColor顏色的背景
    canvas.drawRect(iconRect, paint);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
    paint.setAlpha(255);
    //在mBitmap上繪制以iconBackgroundColor顏色為Dst,DST_IN模式下的圖標(biāo)
    canvas.drawBitmap(iconBitmap, null, iconRect, paint);
  }
  /**
   * 繪制默認(rèn)狀態(tài)下的字體
   *
   * @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);
  }
  /**
   * 繪制滑動(dòng)到該標(biāo)簽時(shí)的字體
   *
   * @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);
  }
  /**
   * 設(shè)置圖標(biāo)透明度并重繪
   *
   * @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();
    }
  }
  /**
   * 判斷當(dāng)前是否為UI線程,是則直接重繪,否則調(diào)用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";
  /**
   * 保存狀態(tài)
   *
   * @return Parcelable
   */
  @Override
  protected Parcelable onSaveInstanceState() {
    Bundle bundle = new Bundle();
    bundle.putParcelable(STATE_INSTANCE, super.onSaveInstanceState());
    bundle.putFloat(STATE_ALPHA, mAlpha);
    return bundle;
  }
  /**
   * 恢復(fù)狀態(tài)
   *
   * @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);
    }
  }
}

然后在布局文件中聲明使用,這里不需要每個(gè)自定義屬性都使用到,因?yàn)槲乙蔡峁┝四J(rèn)值

<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="發(fā)現(xiàn)" />
    <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>

因?yàn)橹鹘缑媸荲iewPager,這里就需要一個(gè)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代碼如下,重點(diǎn)是對(duì)viewPager進(jìn)行滑動(dòng)監(jiān)聽,根據(jù)滑動(dòng)偏移量來動(dòng)態(tài)改變透明度alpha,從而實(shí)現(xiàn)顏色漸變效果

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[]{"微信", "通訊錄", "發(fā)現(xiàn)", "我"};
    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狀態(tài)
   */
  private void resetTabsStatus() {
    for (int i = 0; i < tabIndicators.size(); i++) {
      tabIndicators.get(i).setIconAlpha(0);
    }
  }
  /**
   * 如果是直接點(diǎn)擊圖標(biāo)來跳轉(zhuǎn)頁面的話,position值為0到3,positionOffset一直為0.0
   * 如果是通過滑動(dòng)來跳轉(zhuǎn)頁面的話
   * 假如是從第一頁滑動(dòng)到第二頁
   * 在這個(gè)過程中,positionOffset從接近0逐漸增大到接近1.0,滑動(dòng)完成后又恢復(fù)到0.0,而position只有在滑動(dòng)完成后才從0變?yōu)?
   * 假如是從第二頁滑動(dòng)到第一頁
   * 在這個(gè)過程中,positionOffset從接近1.0逐漸減小到0.0,而position一直是0
   *
   * @param position       當(dāng)前頁面索引
   * @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) {
  }
}

上述內(nèi)容就是Android 中怎么實(shí)現(xiàn)微信底部漸變Tab效果,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

文章題目:Android中怎么實(shí)現(xiàn)微信底部漸變Tab效果
轉(zhuǎn)載源于:http://bm7419.com/article38/jdiopp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)公司面包屑導(dǎo)航、網(wǎng)站改版響應(yīng)式網(wǎng)站、關(guān)鍵詞優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)