看了一位大神的博客,发现他有模仿微信界面实现,我决定向大神看齐!继续努力。
因为我不会制作动画,所以只能图片加说明了:
1,标题栏下面是是一个ViewPager,适配器里面的item是一个个Fragment,这个比较简单
2,ViewPager下面是一排自定义的按钮控件(继承View),随着ViewPager的滑动,字体的透明度会有一个渐变的效果,就像微信界面一样!
我们先自定义控件ColorChange_Iv_Tv,继承View
1,自定属性:前面的四条属性使我们需要的,后面的两条属性是,微信截取图片功能的实现,因为都是仿微信所以写到了一起
好的,我们需要的属性分别是:图标:icon;颜色:color;文本内容:text;文本的大小:text_size
<?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="text_size" format="dimension"></attr>
<declare-styleable name="ColorChange_Iv_Tv">
<attr name="icon"></attr>
<attr name="color"></attr>
<attr name="text"></attr>
<attr name="text_size"></attr>
</declare-styleable>
<attr name="horizontal_padding" format="dimension"></attr>
<declare-styleable name="ClipImageLayout">
<attr name="icon"></attr>
<attr name="horizontal_padding"></attr>
</declare-styleable>
</resources>
2,自定义属性后自然要拿到我们自定义属性的值:
private Bitmap iconBitmap;// 小图标对象
private String text;// 文本对象
private float text_size;// 文本大小
private int color;// 选中后的颜色
private float iconAlpha = 0f;// 透明度,越小越透明
private Paint mPaint;//画笔对象
private Canvas iconCanvas;//绘制icon的画布对象
private Rect textBound;// 文本的范围
private Rect iconBound;// 图标的范围
public ColorChange_Iv_Tv(Context context) {
this(context, null, 0);
}
public ColorChange_Iv_Tv(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ColorChange_Iv_Tv(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typeArray = context.obtainStyledAttributes(attrs,
R.styleable.ColorChange_Iv_Tv);
int n = typeArray.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = typeArray.getIndex(i);
switch (attr) {
case R.styleable.ColorChange_Iv_Tv_color:
color = typeArray.getColor(R.styleable.ColorChange_Iv_Tv_color,
Color.BLUE);
break;
case R.styleable.ColorChange_Iv_Tv_icon:
BitmapDrawable iconDraw = (BitmapDrawable) typeArray
.getDrawable(R.styleable.ColorChange_Iv_Tv_icon);
iconBitmap=iconDraw.getBitmap();
break;
case R.styleable.ColorChange_Iv_Tv_text:
text = typeArray.getString(R.styleable.ColorChange_Iv_Tv_text);
break;
case R.styleable.ColorChange_Iv_Tv_text_size:
text_size = typeArray.getDimension(
R.styleable.ColorChange_Iv_Tv_text_size, TypedValue
.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10,
getResources().getDisplayMetrics()));
break;
}
}
typeArray.recycle();
mPaint=new Paint();
mPaint.setTextSize(text_size);
mPaint.setColor(Color.BLACK);
mPaint.setAlpha(255);
textBound=new Rect();
mPaint.getTextBounds(text, 0, text.length(), textBound);
}
我们可以看到,在构造方法中我们完成了,自定义属性的获取,并且还初始化了画笔对象mPaint, 同时也获得了文本对象的范围!
包含在textBound矩阵中!
3,重写onMeasure方法,实现对布局的调整!
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width=getMeasuredWidth();
int height=getMeasuredHeight();
int iconWith=Math.min(width-getPaddingLeft()-getPaddingRight(),
height-textBound.height()-getPaddingTop()-getPaddingBottom());
int left=width/2-iconWith/2;
int top=height/2-(iconWith+textBound.height())/2;
iconBound=new Rect(left, top, left+iconWith, top+iconWith);
}icon的宽度,取横纵方向剩余空间的较小值!
确定包含icon的正方形!
4,重写onDraw方法,绘图,这个是关键点:
@Override
protected void onDraw(Canvas canvas) {
int alpha=(int) Math.ceil(255*iconAlpha);
//先绘制了,里层没有效果的图片
canvas.drawBitmap(iconBitmap, null, iconBound, null);
drawTextBlack(canvas, alpha);
//绘制了带颜色的文本和图片
drawText(canvas,alpha);
drawIcon(canvas,alpha);
}
//绘制底层的文本
private void drawTextBlack(Canvas canvas,int alpha){
mPaint.reset();
mPaint.setTextSize(text_size);
mPaint.setColor(0xff333333);
mPaint.setAlpha(255-alpha);
canvas.drawText(text, iconBound.left+iconBound.width()/2-textBound.width()/2,
iconBound.bottom+textBound.height(), mPaint);
}
//绘制文本
private void drawText(Canvas canvas,int alpha){
mPaint.reset();
mPaint.setTextSize(text_size);
mPaint.setColor(color);
mPaint.setAlpha(alpha);//要先设置颜色在设置,透明度才能出效果
//Log.i("wangsongbin", alpha+"");
canvas.drawText(text, iconBound.left+iconBound.width()/2-textBound.width()/2,
iconBound.bottom+textBound.height(), mPaint);
}
//绘制icon
private void drawIcon(Canvas canvas,int alpha){
Bitmap bitmap=Bitmap.createBitmap(iconBound.width(),
iconBound.height(), Config.ARGB_8888);
Canvas iconCanvas=new Canvas(bitmap);
mPaint.reset();
mPaint.setColor(color);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setAlpha(alpha);
//先绘制了颜色
iconCanvas.drawRect(0,0,iconBound.width(),iconBound.height(), mPaint);
//再设置,Xfermode的<span style="font-family: Arial, Helvetica, sans-serif;">PorterDuff.Mode.DST_IN</span><span style="font-family: Arial, Helvetica, sans-serif;">模式,即只显示被覆盖的地方,如果有不明白,请看<a target=_blank href="http://blog.youkuaiyun.com/wangsongbin893603021/article/details/45012015">点击打开链接</a></span>
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setAlpha(255);
iconCanvas.drawBitmap(iconBitmap,
null, new RectF(0, 0, iconBound.width(), iconBound.height()), mPaint);
canvas.drawBitmap(bitmap, null,iconBound, null);
}最后,给个方法接口,让用户动态设置透明度,达到渐变的效果
//设置透明度
public void setIconAlpha(float iconAlpha){
this.iconAlpha=iconAlpha;
if(Looper.getMainLooper()==Looper.myLooper()){
invalidate();
}else{
postInvalidate();
}
}最后,没了保证,用户的界面发生横竖屏切换导致的activity重启,导致自定义控件的数据丢失,我重写了:onSaveInstanceState,和onRestoreInstanceState!
具体代码:
private final String instance_state="instance_state";
private final String state_alpha="state_alpha";
@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle=new Bundle();
bundle.putParcelable(instance_state, super.onSaveInstanceState());
bundle.putFloat(state_alpha, iconAlpha);
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if(state instanceof Bundle){
Bundle bundle=(Bundle) state;
iconAlpha=bundle.getFloat(state_alpha);
super.onRestoreInstanceState(bundle.getParcelable(instance_state));
}else{
super.onRestoreInstanceState(state);
}
}到此自定控件就已经完成了。现在是利用的时候了!
先看一下MainActivity的布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:wang="http://schemas.android.com/apk/res/com.wang.demo_weixin_60_ui"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.wang.demo_weixin_60_ui.MainActivity" >
<android.support.v4.view.ViewPager
android:id="@+id/vp_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="@+id/ll_tab">
</android.support.v4.view.ViewPager>
<LinearLayout
android:id="@+id/ll_tab"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:background="@drawable/tabbg"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<com.wang.demo_weixin_60_ui.view.ColorChange_Iv_Tv
android:id="@+id/tabview_one"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="fill_parent"
android:padding="5dp"
wang:icon="@drawable/ic_menu_start_conversation"
wang:color="#ff0000"
wang:text="微信"
wang:text_size="12sp"/>
<com.wang.demo_weixin_60_ui.view.ColorChange_Iv_Tv
android:id="@+id/tabview_two"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="fill_parent"
android:padding="5dp"
wang:icon="@drawable/ic_menu_friendslist"
wang:color="#ff0000"
wang:text="通讯录"
wang:text_size="12sp"/>
<com.wang.demo_weixin_60_ui.view.ColorChange_Iv_Tv
android:id="@+id/tabview_three"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="fill_parent"
android:padding="5dp"
wang:icon="@drawable/ic_menu_emoticons"
wang:color="#ff0000"
wang:text="发现"
wang:text_size="12sp"/>
<com.wang.demo_weixin_60_ui.view.ColorChange_Iv_Tv
android:id="@+id/tabview_four"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="fill_parent"
android:padding="5dp"
wang:icon="@drawable/ic_menu_allfriends"
wang:color="#ff0000"
wang:text="我"
wang:text_size="12sp"/>
</LinearLayout>
</RelativeLayout>
其次是MainActivity中的利用,其中最主要的监听是:
private void registerListener() {
vp_content.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int positon, float positonOffSet, int positionOffsetPixels) {
if(positonOffSet>0){
ColorChange_Iv_Tv left=tabList.get(positon);
ColorChange_Iv_Tv right=tabList.get(positon+1);
left.setIconAlpha(1-positonOffSet);
right.setIconAlpha(positonOffSet);
//这段代码有不明白的,可以把positionOffSet打印出来,在logcat里面比较一下
}
}
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
});
}
在下面都是很简单的内容,大家直接看代码哈!
源代码下载
312

被折叠的 条评论
为什么被折叠?



