亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

仿微信底部漸變Tab

2019-11-09 14:39:22
字體:
來源:轉載
供稿:網友

先來看一下效果圖 這里寫圖片描述

除了第三個的發現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) { }}

這里也提供源代碼下載: CSDN:仿微信底部漸變Tab GitHub:仿微信底部漸變Tab


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
一区二区三区日韩在线| 国产视频亚洲精品| 亚洲国产91精品在线观看| 日韩亚洲综合在线| 91产国在线观看动作片喷水| 国产一区二区激情| 尤物九九久久国产精品的分类| 欧美激情一区二区三区高清视频| 国内精品小视频| 国内成人精品一区| 青青久久av北条麻妃海外网| 亚洲精品v天堂中文字幕| 国产亚洲精品美女久久久| 亚洲free性xxxx护士白浆| 久久亚洲精品小早川怜子66| 黄色成人av网| 亚洲男人天堂2024| 欧美精品免费看| 亚洲香蕉成视频在线观看| 国产精品男人爽免费视频1| 色综合色综合久久综合频道88| 成人妇女免费播放久久久| 国产精品视频最多的网站| 欧美高跟鞋交xxxxxhd| 色偷偷91综合久久噜噜| 亚洲jizzjizz日本少妇| 91高潮在线观看| 亚洲国产高清福利视频| 奇米成人av国产一区二区三区| 欧美成人免费大片| 亚洲精品国产综合区久久久久久久| 97av在线影院| 久久精品成人动漫| 久久久成人精品| 欧美一级电影免费在线观看| 亚洲国产精品视频在线观看| 日韩高清电影免费观看完整| 91久久精品日日躁夜夜躁国产| 精品爽片免费看久久| 成人激情免费在线| 91禁国产网站| 日韩动漫免费观看电视剧高清| 美女精品久久久| 国产精品久久久久久久一区探花| 黄色91在线观看| 国产精品一区二区女厕厕| 日韩av综合中文字幕| 国产a∨精品一区二区三区不卡| 色综合色综合网色综合| 久久精品国产亚洲7777| 欧美国产日韩一区| 亚洲最新中文字幕| 国产福利精品视频| 亚洲自拍中文字幕| 欧美一级免费看| 亚洲第一av在线| 亚洲精品国产精品久久清纯直播| 欧美激情视频在线| 欧美另类在线观看| 92国产精品久久久久首页| 久久在线观看视频| 亚洲国产精品成人va在线观看| 黑人狂躁日本妞一区二区三区| 亚洲激情视频网站| 亚洲精品aⅴ中文字幕乱码| 亚洲欧美日韩爽爽影院| 日韩av片永久免费网站| 国产精品一区二区久久国产| 亚洲精品久久久久久久久久久| 亚洲色图第一页| 国产欧美日韩专区发布| 亚洲天堂成人在线| 国产精品视频1区| 午夜精品久久久久久久白皮肤| 亚洲第一网站免费视频| 亚洲嫩模很污视频| 亚洲成人精品久久久| 久热在线中文字幕色999舞| 91亚洲国产成人精品性色| 欧美俄罗斯乱妇| 国产91露脸中文字幕在线| 国产精品视频免费观看www| 97精品伊人久久久大香线蕉| 亚洲国产古装精品网站| 992tv成人免费视频| 欧美大片免费观看在线观看网站推荐| 成人写真视频福利网| 91免费观看网站| 国产免费观看久久黄| 国产精品综合网站| 欧美性在线观看| 亚洲精品国产精品国自产在线| 亚洲免费av网址| 亚洲欧美一区二区精品久久久| 国产91精品久久久久| 国产欧美一区二区三区四区| 91免费在线视频网站| 成人国产精品一区| 色阁综合伊人av| 91tv亚洲精品香蕉国产一区7ujn| 国产精品美腿一区在线看| 亚洲午夜未删减在线观看| 成人乱人伦精品视频在线观看| 欧美高清在线播放| 久久久久久亚洲精品中文字幕| 色综合老司机第九色激情| 136fldh精品导航福利| 日韩动漫免费观看电视剧高清| 国产日韩中文字幕| 亚洲影视九九影院在线观看| 亚洲精品福利在线观看| 久久久久亚洲精品| 精品露脸国产偷人在视频| 欧美精品亚州精品| 国产精品亚洲激情| 91天堂在线视频| 91久久久国产精品| 美女久久久久久久| 久久免费高清视频| 欧美亚洲成人免费| 欧美激情一区二区三级高清视频| 97人洗澡人人免费公开视频碰碰碰| 久久成人一区二区| 欧美大片免费观看在线观看网站推荐| 欧美精品国产精品日韩精品| 久久激情五月丁香伊人| 亚洲国产成人在线视频| 欧美日韩在线观看视频小说| 欧美夫妻性生活视频| 欧美与黑人午夜性猛交久久久| 欧美激情综合色综合啪啪五月| 欧美午夜激情小视频| xx视频.9999.com| 高清视频欧美一级| 性夜试看影院91社区| 欧美大片免费观看在线观看网站推荐| 91美女片黄在线观看游戏| 欧美日韩国产丝袜另类| 色一情一乱一区二区| 午夜精品久久久久久久99热浪潮| 亚洲aⅴ日韩av电影在线观看| 中文字幕亚洲综合久久| 97色在线视频观看| www.亚洲免费视频| 成人免费午夜电影| 狠狠做深爱婷婷久久综合一区| 亚洲精品国产品国语在线| www.国产精品一二区| 美日韩精品免费观看视频| 91影院在线免费观看视频| 欧美福利视频网站| 欧美激情视频在线| 亚洲视屏在线播放| 国产98色在线| 欧美电影免费看| 69久久夜色精品国产69| 日韩欧美在线视频免费观看| 这里只有精品丝袜| 97色伦亚洲国产| 97超级碰碰碰久久久| 国产成人精品优优av| 国产午夜一区二区| 中文字幕9999| 国产亚洲欧美日韩美女|