仿微信6.0界面

/**
 * 自定义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);
    }
}

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值