先来张图
菜单文件:
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" > <item android:id="@+id/action_search" android:actionViewClass="android.widget.SearchView" android:icon="@drawable/actionbar_search_icon" android:showAsAction="ifRoom|collapseActionView" android:title="@string/action_search"/> <item android:id="@+id/action_scan" android:icon="@drawable/ic_menu1" android:title="@string/menu_scan"/> <item android:id="@+id/action_group" android:icon="@drawable/ic_menu2" android:title="@string/menu_group"/> <item android:id="@+id/action_add_friend" android:icon="@drawable/ic_menu3" android:title="@string/menu_feedback"/> <item android:id="@+id/action_feedback" android:icon="@drawable/ic_menu4" android:title="@string/menu_addfriend"/> </menu>
// 设置ActionBar Icon图标不显示 getActionBar().setDisplayShowHomeEnabled(false);
// 如果ActionBar右边的设置图标不显示,可以通过以下方法设置 private void setOverflowButtonAlways() { try { ViewConfiguration config = ViewConfiguration.get(this); Field menuKey = ViewConfiguration.class .getDeclaredField("sHasPermanentMenuKey"); menuKey.setAccessible(true); menuKey.setBoolean(config, false); } catch (Exception e) { e.printStackTrace(); } }
菜单中icon图标默认是不显示的,像这样:
可以通过在Activity中覆盖以下方法设置:
@Override public boolean onMenuOpened(int featureId, Menu menu) { if (featureId == Window.FEATURE_ACTION_BAR && menu != null) { if (menu.getClass().getSimpleName().equals("MenuBuilder")) { try { Method method = menu.getClass().getDeclaredMethod( "setOptionalIconsVisible", Boolean.TYPE); method.setAccessible(true); method.invoke(menu, true); } catch (Exception e) { e.printStackTrace(); } } } return super.onMenuOpened(featureId, menu); }
效果如下:
以上是ActionBar。下面来看底部的几个按钮:
xml文件里面就是一个LinearLayout包裹了四个一样的自定义控件,为了方便,我这里只贴出一个,完整的请查看源码
<com.example.weixin.ChangeColorText android:id="@+id/id_indicator_one" android:padding="5dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_weight="1" hzx:icon="@drawable/ic_menu_start_conversation" hzx:text="@string/tab_contact" hzx:textSize="12sp" hzx:color="#ff45c01a" />
这个控件使用了四个自定义属性,attr文件:
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="icon" format="reference"></attr> <attr name="color" format="color"></attr> <attr name="text" format="string"></attr> <attr name="textSize" format="dimension"></attr> <declare-styleable name="ChangeColorText"> <attr name="icon" /> <attr name="color"/> <attr name="text" /> <attr name="textSize" /> </declare-styleable> </resources>
ChangeColorTex类如下:
1 public class ChangeColorText extends View { 2 3 int mColor = 0xFF45C01A; 4 String mText = "微信"; 5 int mTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 6 12, getResources().getDisplayMetrics()); 7 8 Canvas mCanvas; 9 Bitmap mBitmap; 10 Paint mPaint; 11 Bitmap mIconBitma; 12 13 float mAlpha; 14 Rect mIconRect; 15 Rect mTextBound; 16 17 Paint mTextPaint; 18 19 public ChangeColorText(Context context) { 20 super(context); 21 }
以上是一些变量,关键的是下面这个构造方法:
1 /**获取自定义属性的值*/ 2 public ChangeColorText(Context context, AttributeSet attrs) { 3 super(context, attrs); 4 5 TypedArray a = context.obtainStyledAttributes(attrs, 6 R.styleable.ChangeColorText); 7 8 // 获取各个自定义属性的值 9 int n = a.getIndexCount(); 10 for (int i = 0; i < n; i++) { 11 int attr = a.getIndex(i); 12 switch (attr) { 13 case R.styleable.ChangeColorText_icon: 14 BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(attr); 15 mIconBitma = drawable.getBitmap(); 16 break; 17 case R.styleable.ChangeColorText_color: 18 mColor = a.getColor(attr, 0xFF45C01A); 19 break; 20 case R.styleable.ChangeColorText_text: 21 mText = a.getString(attr); 22 break; 23 24 case R.styleable.ChangeColorText_textSize: 25 mTextSize = (int) a.getDimension(attr, TypedValue 26 .applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, 27 getResources().getDisplayMetrics())); 28 break; 29 default: 30 break; 31 } 32 } 33 34 a.recycle(); // 这里一定要回收掉 35 36 // 初始化一些变量 37 mTextBound = new Rect(); 38 mTextPaint = new Paint(); 39 mTextPaint.setTextSize(mTextSize); 40 mTextPaint.setColor(0xff555555); 41 42 mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound); 43 }
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 测量图标的宽高 super.onMeasure(widthMeasureSpec, heightMeasureSpec); int iconWidth = Math.min(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), getMeasuredHeight() - getPaddingTop() - getPaddingBottom() - mTextBound.height()); int left = getMeasuredWidth() / 2 - iconWidth / 2; int top = (getMeasuredHeight() - mTextBound.height()) / 2 - iconWidth / 2; mIconRect = new Rect(left, top, left + iconWidth, top + iconWidth); }
@Override protected void onDraw(Canvas canvas) { // 绘制控件 canvas.drawBitmap(mIconBitma, null, mIconRect,null); int alpha = (int) Math.ceil(255 * mAlpha); // 1、内存去准备mBitmap , setAlpha , 纯色 ,xfermode , 图标 setUpTargetBitmap(alpha); // 2、绘制原文本 drawSourceText(canvas,alpha); // 3、绘制变色的文本 drawTargetText(canvas,alpha); canvas.drawBitmap(mBitmap, 0, 0,null); }
/** 在内存中绘制可变色的Icon */ private void setUpTargetBitmap(int alpha) { mBitmap = Bitmap.createBitmap(getMeasuredWidth(),getMeasuredHeight(),Config.ARGB_8888); mCanvas = new Canvas(mBitmap); mPaint = new Paint(); mPaint.setColor(mColor); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setAlpha(alpha); mCanvas.drawRect(mIconRect, mPaint); mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); mPaint.setAlpha(255); mCanvas.drawBitmap(mIconBitma, null, mIconRect,mPaint); }
/** 绘制变色的文本*/ private void drawTargetText(Canvas canvas, int alpha) { mTextPaint.setColor(mColor); mTextPaint.setAlpha(alpha); int x = getMeasuredWidth()/2 - mTextBound.width()/2; int y = mIconRect.bottom + mTextBound.height(); canvas.drawText(mText,x , y, mTextPaint); }
/**绘制原文本*/ private void drawSourceText(Canvas canvas, int alpha) { mTextPaint.setColor(0xff333333); mTextPaint.setAlpha(255); int x = getMeasuredWidth()/2 - mTextBound.width()/2; int y = mIconRect.bottom + mTextBound.height(); canvas.drawText(mText,x , y, mTextPaint); }
以下两个方法用来保存当屏幕横竖屏切换时当前View的状态:
private static final String INSTANCE_STATUS = "instance_status"; private static final String STATUS_ALPHA = "status_alpha"; @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putParcelable(INSTANCE_STATUS, super.onSaveInstanceState()); bundle.putFloat(STATUS_ALPHA, mAlpha); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { Bundle bundle = (Bundle) state; mAlpha = bundle.getFloat(STATUS_ALPHA); super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATUS)); return; } super.onRestoreInstanceState(state); }
提供一个public方法用来改变View的颜色深度:
public void setIconAlpha(float alpha){ this.mAlpha = alpha; invalidateView(); }
/** 重绘 */ private void invalidateView() { if (Looper.getMainLooper() == Looper.myLooper()) { invalidate(); }else { postInvalidate(); } }
到这自定义View就写完了。
最后Activity里面设置mViewPager.setOnPageChangeListener(this);在OnPageChangeListener的onPageScrolled中
调用setIconAlpha(float alpha)方法:
// 以下代码是切换Fragment中View的透明度,不需要可以注释掉
@Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (positionOffset > 0) { ChangeColorText left = mTabIndicators.get(position); ChangeColorText right = mTabIndicators.get(position + 1); left.setIconAlpha(1 - positionOffset); right.setIconAlpha(positionOffset); mTabs.get(position).getView().setAlpha(1 - positionOffset); mTabs.get(position + 1).getView().setAlpha(positionOffset); } }
感谢您的阅读
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步