仿微信6.0笔记

1.ActionBar

设置样式,改变overflowButtonstyle;反射,改变 带图标下拉item。

2.ViewPager+Fragement 

推荐:使用
设置setArguments Bundle (代替传参)

//从第一页到第二页 positionOffset 0~1
//从第二页到第一页 positionOffset 1~0

3.TabIndicator(自定义控件)


一.底部滑动渐变

原理:底部摆放四个自定义控件,控件内部在一个Bitmap上绘制纯色并设置Xfermodes 为DstIn,然后在Bitmap上绘制对应icon,最后通过View的Canvas绘制出来,利用ViewPager的onPageScrolled时的参数positionOffset的变化设置自定义控件的透明度。

自定义View

1.自定义attr.xml

2.布局文件中使用

3.构造方法中获取自定义属性
4.onMeasure中计算Icon区域大小(Rect mIconRect

5.onDraw 使用从自定义属性中获取的Bitmap来绘制Icon 根据文字画笔 绘制原文字以及变化的文字


dimension(单位sp) 

declare-styleable name="自定义View的名称"

1.自定义attr.xml

<resources>

    <attr name="icon1" format="reference"></attr>
    <attr name="color1" format="color"></attr>
    <attr name="text" format="string"></attr>
    <attr name="text_size" format="dimension"></attr>

    <declare-styleable name="ChangeColorIconWithText">
        <attr name="icon1"></attr>
        <attr name="color1"></attr>
        <attr name="text"></attr>
        <attr name="text_size"></attr>
    </declare-styleable>

</resources>
2.布局文件中使用

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:hyman="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:background="@drawable/tab_bg"
    android:orientation="horizontal" >

    <wechat6_0.example.com.wechat6_0.ChangeColorIconWithText
        android:id="@+id/id_indicator_one"
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        android:padding="5dp"
        hyman:icon1="@mipmap/ic_menu_start_conversation"
        hyman:text="@string/app_name"
        hyman:text_size="12sp"
        hyman:color1="#ff45c01a" />

    <wechat6_0.example.com.wechat6_0.ChangeColorIconWithText
        android:id="@+id/id_indicator_two"
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        android:padding="5dp"
        hyman:icon1="@mipmap/ic_menu_friendslist"
        hyman:text="@string/tab_contact"
        hyman:text_size="12sp"
        hyman:color1="#ff45c01a" />

3.构造方法中获取自定义属性(根据文字长度设置文字画笔Paint
,并获取文字区域大小

public ChangeColorIconWithText(Context context, AttributeSet attrs,
      int defStyleAttr)
{
   super(context, attrs, defStyleAttr);
   TypedArray a = context.obtainStyledAttributes(attrs,
         R.styleable.ChangeColorIconWithText);
   int n = a.getIndexCount();
   for (int i = 0; i < n; i++)
   {
      int attr = a.getIndex(i);
      switch (attr)
      {
      case R.styleable.ChangeColorIconWithText_icon1:
         BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(attr);
         mIconBitmap = drawable.getBitmap();
         break;
      case R.styleable.ChangeColorIconWithText_color1:
         mColor = a.getColor(attr, 0xFF45C01A);
         break;
      case R.styleable.ChangeColorIconWithText_text:
         mText = a.getString(attr);
         break;
      case R.styleable.ChangeColorIconWithText_text_size:
         mTextSize = (int) a.getDimension(attr, TypedValue
               .applyDimension(TypedValue.COMPLEX_UNIT_SP, 12,
                     getResources().getDisplayMetrics()));
         break;
      }
   }
   //使用context.obtainStyledAttributes(attrs,R.styleable.ChangeColorIconWithText)
   // 记得recycle
   a.recycle();
   mTextBound = new Rect();
   mTextPaint = new Paint();
   mTextPaint.setTextSize(mTextSize);
   mTextPaint.setColor(0Xff555555);//灰色
   mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);
}
4. onMeasure中计算Icon区域大小(Rect mIconRect)

private int mColor = 0xFF45C01A;
private Bitmap mIconBitmap;
private String mText = "微信";
//设置默认12sp COMPLEX_UNIT_SP
private int mTextSize = (int) TypedValue.applyDimension(
      TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics());

private Canvas mCanvas;
private Bitmap mBitmap;
private Paint mPaint;

private float mAlpha;
private Paint mTextPaint;
private Rect mIconRect;
private Rect mTextBound;

/*
   View有两种可能宽大于高 宽小于高
   View的宽度-leftpadding-rightpadding
   View的高度-topPadding-mTextBound.height
   icon的边长为下列两个的最小值
 */
   @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() / 2 - (mTextBound.height() + iconWidth)
            / 2;
      mIconRect = new Rect(left, top, left + iconWidth, top + iconWidth);
   }

5.onDraw 使用从自定义属性中获取的Bitmap来绘制Icon 根据文字画笔 绘制原文字以及变化的文字

内存中绘制变色的icon

@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、绘制原文本 ; 2、绘制变色的文本
   drawSourceText(canvas, alpha);
   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));
//显示两者的交集且前者(mColor)的颜色
   mPaint.setAlpha(255);
   mCanvas.drawBitmap(mIconBitmap, null, mIconRect, mPaint);
}

/**  * 绘制变色的文本  *  * @param canvas  * @param alpha  */ 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);
}

/**  * 绘制原文本  * getMeasuredWidth View宽度  * @param canvas  * @param alpha  */ private void drawSourceText(Canvas canvas, int alpha)
{
   mTextPaint.setColor(0xff333333);
   mTextPaint.setAlpha(255 - alpha);
   int x = getMeasuredWidth() / 2 - mTextBound.width() / 2;
   int y = mIconRect.bottom + mTextBound.height();
   canvas.drawText(mText, x, y, mTextPaint);

}
外部设置icon的Alpha并根据主\其他线程 刷新控件

public void setIconAlpha(float alpha)
{
   this.mAlpha = alpha;
   invalidateView();
}

/**  * 重绘  */ private void invalidateView()
{
   if (Looper.getMainLooper() == Looper.myLooper())
   {
      invalidate();
   } else
   {
      postInvalidate();
   }
}


防止Activity回收(长期至于后台的被回收)总结

(模拟回收-当旋转时Activiy会重建)

实现目的:activity的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);
}


你可能感兴趣的:(仿微信6.0笔记)