/** * 自定义View * 1. attr.xml * 2. 布局文件中使用 * 3. 构造方法中获取自定义属性 * 4. onMeasure * 5. onDraw * 6. xformode的原理 * * onPageScrolled(int positiFon, float positionOffset, int positionOffsetPixels) * 从第一页到第二页 * position = 0 * positionOffset 0.0 ~ 1.0 * * 从第二页到第一页 * position = 0 * positionOffset 1.0 ~ 0.0 * * * 高仿微信6.0主界面 * 1. ActionBar 设置样式,改变overflowButtonStyle; 反射,改变一些设置 * 2. ViewPager + Fragment * 3. TabItemView 自定义View */ public class MainActivity extends AppCompatActivity implements View.OnClickListener, ViewPager.OnPageChangeListener { private ViewPager mViewPager; private List<Fragment> mTabs = new ArrayList<>(); private String[] mTitles = new String[]{"First fragment", "Second fragment", "Three fragment", "Four fragment"}; private FragmentPagerAdapter mAdapter; private List<TabItemView> mTabItemIndicators = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); toolbar.setTitleTextColor(Color.WHITE); toolbar.setOverflowIcon(ContextCompat.getDrawable(this, R.mipmap.actionbar_add_icon)); setSupportActionBar(toolbar); initView(); initDatas(); mViewPager.setAdapter(mAdapter); initEvent(); } private void initEvent() { mViewPager.addOnPageChangeListener(this); } private void initDatas() { for (String title : mTitles) { TabFragment tabFragment = TabFragment.newInstance(title); mTabs.add(tabFragment); } mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) { @Override public Fragment getItem(int position) { return mTabs.get(position); } @Override public int getCount() { return mTabs.size(); } }; } private void initView() { mViewPager = (ViewPager) findViewById(R.id.viewpager); TabItemView one = (TabItemView) findViewById(R.id.id_indicator_one); mTabItemIndicators.add(one); TabItemView two = (TabItemView) findViewById(R.id.id_indicator_two); mTabItemIndicators.add(two); TabItemView three = (TabItemView) findViewById(R.id.id_indicator_three); mTabItemIndicators.add(three); TabItemView four = (TabItemView) findViewById(R.id.id_indicator_four); mTabItemIndicators.add(four); one.setOnClickListener(this); two.setOnClickListener(this); three.setOnClickListener(this); four.setOnClickListener(this); one.setIconAlpha(1.0f); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return super.onCreateOptionsMenu(menu); } private void setOverflowButtonAlways() { ViewConfiguration config = ViewConfiguration.get(this); try { Field menuKey = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey"); menuKey.setAccessible(true); try { menuKey.setBoolean(config, false); } catch (IllegalAccessException e) { e.printStackTrace(); } } catch (NoSuchFieldException e) { e.printStackTrace(); } } @Override public boolean onMenuOpened(int featureId, Menu menu) { if (featureId == 108 && menu != null) { // Window.FEATURE_ACTION_BAR if (menu.getClass().getSimpleName().equals("MenuBuilder")) { try { Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); m.setAccessible(true); m.invoke(menu, true); } catch (Exception e) { e.printStackTrace(); } } } return super.onMenuOpened(featureId, menu); } @Override public void onClick(View v) { resetOtherTabs(); switch (v.getId()) { case R.id.id_indicator_one: mTabItemIndicators.get(0).setIconAlpha(1.0f); mViewPager.setCurrentItem(0, false); break; case R.id.id_indicator_two: mTabItemIndicators.get(1).setIconAlpha(1.0f); mViewPager.setCurrentItem(1, false); break; case R.id.id_indicator_three: mTabItemIndicators.get(2).setIconAlpha(1.0f); mViewPager.setCurrentItem(2, false); break; case R.id.id_indicator_four: mTabItemIndicators.get(3).setIconAlpha(1.0f); mViewPager.setCurrentItem(3, false); break; } } /** * 重置其他TabIndicator的颜色 */ private void resetOtherTabs() { for (int i = 0; i < mTabItemIndicators.size(); i++) { mTabItemIndicators.get(i).setIconAlpha(0); } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { // 手指左滑(0, 1) 手指右滑(1, 0) if (positionOffset > 0) { TabItemView left = mTabItemIndicators.get(position); TabItemView right = mTabItemIndicators.get(position + 1); left.setIconAlpha(1 - positionOffset); right.setIconAlpha(positionOffset); } } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { } }
public class TabItemView extends View { private int mColor = 0xFF45C01A; private Bitmap mIconBitmap; private String mText = "微信"; private int mTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, getResources().getDisplayMetrics()); private Canvas mCanvas; private Bitmap mBitmap; private Paint mPaint; private float mAlpha ; private Rect mIconRect; private Rect mTextBound; private Paint mTextPain; public TabItemView(Context context) { this(context, null); } public TabItemView(Context context, AttributeSet attrs) { this(context, attrs, 0); } /** * 获取自定义属性的值 * @param context * @param attrs * @param defStyleAttr */ public TabItemView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabItemView); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.TabItemView_wx_icon: BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(attr); mIconBitmap = drawable.getBitmap(); break; case R.styleable.TabItemView_wx_color: mColor = a.getColor(attr, 0xFF45C01A); break; case R.styleable.TabItemView_wx_text: mText = a.getString(attr); break; case R.styleable.TabItemView_wx_text_size: mTextSize = (int) a.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, getResources().getDisplayMetrics())); break; } } a.recycle(); mTextBound = new Rect(); mTextPain = new Paint(); mTextPain.setTextSize(mTextSize); mTextPain.setColor(0xff555555); mTextPain.getTextBounds(mText, 0, mText.length(), mTextBound); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int iconWidth = Math.min(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), getMeasuredHeight() - getPaddingBottom() - 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(mIconBitmap, null, mIconRect, null); // 返回大于或者等于指定表达式的最小整数 int alpha = (int) Math.ceil(255 * mAlpha); // 内存中准备mBitmap, setAlpha, 纯色, xfermode, 图标 setupTargetBitmap(alpha); // 1. 绘制显示的原文本 drawSourceText(canvas, alpha); // 2. 绘制变色的文本 drawTargetText(canvas, alpha); // 绘制变色的图标 [和显示的图标具有共同的rect] 是重叠的,只是变色部分有个透明度变化 canvas.drawBitmap(mBitmap, 0, 0, null); } /** * 绘制变色的文本 * @param canvas * @param alpha 纯色或者透明 */ private void drawTargetText(Canvas canvas, int alpha) { mTextPain.setColor(mColor); mTextPain.setAlpha(alpha); int x = getMeasuredWidth() / 2 - mTextBound.width() / 2; int y = mIconRect.bottom + mTextBound.height(); canvas.drawText(mText, x, y, mTextPain); } /** * 绘制原文本 * @param canvas * @param alpha 该参数可省略 */ private void drawSourceText(Canvas canvas, int alpha) { mTextPain.setColor(0xff333333); mTextPain.setAlpha(255 - alpha); int x = getMeasuredWidth() / 2 - mTextBound.width() / 2; int y = mIconRect.bottom + mTextBound.height(); canvas.drawText(mText, x, y, mTextPain); } /** * 在内存中绘制可变色的Icon * @param alpha 是针对纯色设置的 */ private void setupTargetBitmap(int alpha) { // 在图标的范围绘制一个纯色 mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); mPaint = new Paint(); mPaint.setColor(mColor); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setAlpha(alpha); // 等于255每个item都有背景色 0就是透明了 mCanvas.drawRect(mIconRect, mPaint); // 取两层绘制交集, 显示下层 [底部是个纯绿色的方型, 上面是个圆形, 取交集后就是一个纯绿色的圆形] mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); // mBitmap就是一个带有纯背景色的图片 mPaint.setAlpha(255); mCanvas.drawBitmap(mIconBitmap, null, mIconRect, mPaint); } public void setIconAlpha(float alpha) { this.mAlpha = alpha; invalidateView(); } private void invalidateView() { if (Looper.getMainLooper() == Looper.myLooper()) { invalidate(); } else { postInvalidate(); } } private static final String INSTANCE_STATUS = "instance_status"; private static final String STATUS_ALPHA = "instance_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); } }