声明:这个方案确实解决不了相对布局的问题,不好意思!
对于单一view中绘制小红点,在此不写了,通常是重写onDraw方法实现的
但是现在需求是:对于实现任意view添加小红点,并且对外开放设置内容、大小、颜色、位置等接口
我昨天看到这个问题,确实没做过实现所有view,开始想到的是能不能用动态代理,进行重绘,但又发现是行不通的,想了很久,我就想起来手机QQ的消息提示方式,QQ消息提示的小红点,有些是可以拖动的,既然可以拖动而且有动画效果,我就觉得小红点应该是一个单独的控件,单独的控件里完全可以设置内容、颜色、位置、动画等,而且不用修改原来的控件,只添加控件,这样符合了开闭原则,嘿嘿,然后就有思路了,把要添加小红点的orginView当做参数传入构造方法,利用orginView得到parentView,将orginView从parentView中去掉,取而代之为一个包含orginView和小红点的framLayout,最终,其实在原来的界面上只是添加了一个小红点控件,不影响原来的代码,有消息来的时候,更新对应的小红点控件就可以了。
但是,后来经过高人提示,这种方案有缺陷:在relativeLayout下此方案不可行,如果为父view是relativeLayout的两个子view添加小红点控件,不可行。。。看代码就明白了,附上链接:http://download.csdn.net/detail/qizhenghao/8002449
下面是自定义的小红点控件,继承自TextView:
package com.bruce.interview.designredpoint.view;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;
import android.widget.TextView;
/**
* Function: 未读消息控件,可以自由设置大小、颜色、位置
* @author qizhenghao
*
*/
public class RedPointView extends TextView {
//设置默认的对齐排列方式
private static final int DEFAULT_MARGIN_DIP = 5;
private static final int DEFAULT_PADDING_DIP = 5;
private int pointMargin;
private int paddingPixels;
//用于保存背景图
private ShapeDrawable pointBg;
// 显示未读条数
private int content = 0;
// 背景颜色
private int colorBg = Color.RED;
// 内容颜色
private int colorContent = Color.WHITE;
// 显示左右位置
private int left_right = Gravity.RIGHT;
// 显示上下位置
private int top_bottom = Gravity.TOP;
// 显示大小
private int sizeContent = 15;
// 背景大小
private int sizeBg = (int) (sizeContent * 1.5);
// 是否显示
private boolean isShown;
private Context context;
private View orginView;
public RedPointView(Context context, View target) {
super(context);
this.context = context;
this.orginView = target;
init();
}
/**
* Fuction: 设置未读条数
*
* @param content
* ,默认为 0
* @author qizhenghao
*/
public void setContent(int content) {
this.content = content;
setText(content + "");
}
/**
* Fuction: 设置内容字体颜色
*
* @param colorContent
* , 默认为 Color.WHITE
* @author qizhenghao
*/
public void setColorContent(int colorContent) {
this.colorContent = colorContent;
setTextColor(colorContent);
}
/**
* Fuction: 设置背景颜色
*
* @param colorBg
* ,默认为 Color.RED
* @author qizhenghao
*/
public void setColorBg(int colorBg) {
this.colorBg = colorBg;
pointBg = getDefaultBackground();
setBackgroundDrawable(pointBg);
}
/**
* Fuction: 设置显示位置
*
* @param left_right
* ,默认为 Gravity.RIGHT
* @param top_bottom
* ,默认为 Gravity.TOP
* @author qizhenghao
*/
public void setPosition(int left_right, int top_bottom) {
this.left_right = left_right;
this.top_bottom = top_bottom;
setPositionParams(left_right, top_bottom);
}
/**
* Fuction: 设置内容字体大小
*
* @param sizeContent
* ,默认为 15,单位默认为 sp,背景随之扩充
* @author qizhenghao
*/
public void setSizeContent(int sizeContent) {
this.sizeContent = sizeContent;
setTextSize(sizeContent);
this.sizeBg = (int) (sizeContent * 1.5);
}
/**
* Function: 显示小红点
*
* @author qizhenghao
*/
public void show() {
this.setVisibility(View.VISIBLE);
isShown = true;
}
/**
* Function: 隐藏小红点
*
* @author qizhenghao
*/
public void hide() {
this.setVisibility(View.GONE);
isShown = false;
}
// 画一个背景
private ShapeDrawable getDefaultBackground() {
int r = sizeBg;
float[] outerR = new float[] { r, r, r, r, r, r, r, r };
RoundRectShape rectShape = new RoundRectShape(outerR, null, null);
ShapeDrawable shap = new ShapeDrawable(rectShape);
shap.getPaint().setColor(colorBg);
return shap;
}
// 设置显示位置参数
private void setPositionParams(int left_right, int top_bottom) {
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.gravity = left_right | top_bottom;
switch (left_right) {
case Gravity.LEFT:
switch (top_bottom) {
case Gravity.TOP:
params.setMargins(pointMargin, pointMargin, 0, 0);
break;
case Gravity.BOTTOM:
params.setMargins(pointMargin, 0, 0, pointMargin);
default:
break;
}
case Gravity.RIGHT:
switch (top_bottom) {
case Gravity.TOP:
params.setMargins(0, pointMargin, pointMargin, 0);
break;
case Gravity.BOTTOM:
params.setMargins(0, 0, pointMargin, pointMargin);
default:
break;
}
break;
default:
break;
}
setLayoutParams(params);
}
/*
* 初始化
*/
private void init() {
pointMargin = dipToPixels(DEFAULT_MARGIN_DIP);
setTypeface(Typeface.DEFAULT_BOLD);
paddingPixels = dipToPixels(DEFAULT_PADDING_DIP);
setPadding(paddingPixels, 0, paddingPixels, 0);
setContent(content);
setColorContent(colorContent);
setSizeContent(sizeContent);
setPosition(left_right, top_bottom);
setColorBg(colorBg);
isShown = false;
if (this.orginView != null) {
restartDraw(this.orginView);
}
}
// 将target从父view中去掉,取而代之为一个包含target和point的framLayout
private void restartDraw(View target) {
LayoutParams lp = target.getLayoutParams();
ViewParent parent = target.getParent();
FrameLayout framLayout = new FrameLayout(context);
ViewGroup viewGroup = (ViewGroup) parent;
int index = viewGroup.indexOfChild(target);
viewGroup.removeView(target);
viewGroup.addView(framLayout, index, lp);
framLayout.addView(target);
framLayout.addView(this);
viewGroup.invalidate();
}
private int dipToPixels(int dip) {
Resources r = getResources();
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip,
r.getDisplayMetrics());
return (int) px;
}
}
package com.bruce.interview.designredpoint.activity;
import com.bruce.interview.designredpoint.R;
import com.bruce.interview.designredpoint.view.RedPointView;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.view.Gravity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
public class TestPointActivity extends Activity {
private Button testBtn = null;
private ImageView testImg = null;
private Button testBtn1 = null;
private ImageView testImg1 = null;
private Button testBtn2 = null;
private ImageView testImg2 = null;
private Button relativeBtn1 = null;
private Button relativeBtn2 = null;
private RedPointView btnPoint3 = null;
private RedPointView btnPoint4 = null;
private RedPointView btnPoint = null;
private RedPointView imgPoint = null;
private RedPointView btnPoint1 = null;
private RedPointView imgPoint1 = null;
private RedPointView btnPoint2 = null;
private RedPointView imgPoint2= null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_point);
findId();
initView();
setListener();
}
private void initView() {
btnPoint = new RedPointView(this, testBtn);
btnPoint.setContent(0);
btnPoint.setSizeContent(10);
btnPoint.setColorContent(Color.BLACK);
btnPoint.setColorBg(Color.RED);
btnPoint.setPosition(Gravity.RIGHT, Gravity.TOP);
imgPoint = new RedPointView(this, testImg);
imgPoint.setContent(0);
imgPoint.setSizeContent(10);
imgPoint.setColorContent(Color.WHITE);
imgPoint.setColorBg(Color.BLACK);
imgPoint.setPosition(Gravity.RIGHT, Gravity.TOP);
btnPoint1 = new RedPointView(this, testBtn1);
btnPoint1.setContent(1);
btnPoint1.setSizeContent(13);
btnPoint1.setColorContent(Color.WHITE);
btnPoint1.setColorBg(Color.RED);
btnPoint1.setPosition(Gravity.RIGHT, Gravity.BOTTOM);
imgPoint1 = new RedPointView(this, testImg1);
imgPoint1.setContent(1);
imgPoint1.setSizeContent(13);
imgPoint1.setColorContent(Color.WHITE);
imgPoint1.setColorBg(Color.BLACK);
imgPoint1.setPosition(Gravity.RIGHT, Gravity.BOTTOM);
btnPoint2 = new RedPointView(this, testBtn2);
btnPoint2.setContent(2);
btnPoint2.setSizeContent(16);
btnPoint2.setColorContent(Color.GREEN);
btnPoint2.setColorBg(Color.YELLOW);
btnPoint2.setPosition(Gravity.LEFT, Gravity.TOP);
imgPoint2 = new RedPointView(this, testImg2);
imgPoint2.setContent(2);
imgPoint2.setSizeContent(16);
imgPoint2.setColorContent(Color.WHITE);
imgPoint2.setColorBg(Color.RED);
imgPoint2.setPosition(Gravity.LEFT, Gravity.BOTTOM);
//注:在relativeLayout下此方案不可行,下面为父view是relativeLayout的两个button添加小红点控件,不可行。。
// btnPoint3 = new RedPointView(this, relativeBtn1);
// btnPoint3.setContent(2);
// btnPoint3.setSizeContent(16);
// btnPoint3.setColorContent(Color.GREEN);
// btnPoint3.setColorBg(Color.YELLOW);
// btnPoint3.setPosition(Gravity.LEFT, Gravity.TOP);
// btnPoint4 = new RedPointView(this, relativeBtn2);
// btnPoint4.setContent(2);
// btnPoint4.setSizeContent(16);
// btnPoint4.setColorContent(Color.GREEN);
// btnPoint4.setColorBg(Color.YELLOW);
// btnPoint4.setPosition(Gravity.LEFT, Gravity.TOP);
}
private void setListener() {
testBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
btnPoint.show();
btnPoint1.show();
btnPoint2.show();
imgPoint.hide();
imgPoint1.hide();
imgPoint2.hide();
}
});
testImg.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
btnPoint.hide();
btnPoint1.hide();
btnPoint2.hide();
imgPoint.show();
imgPoint1.show();
imgPoint2.show();
}
});
}
private void findId() {
testBtn = (Button) findViewById(R.id.test_btn);
testImg = (ImageView) findViewById(R.id.test_img);
testBtn1 = (Button) findViewById(R.id.test_btn1);
testImg1 = (ImageView) findViewById(R.id.test_img1);
testBtn2 = (Button) findViewById(R.id.test_btn2);
testImg2 = (ImageView) findViewById(R.id.test_img2);
relativeBtn1 = (Button) findViewById(R.id.relative_btn1);
relativeBtn2 = (Button) findViewById(R.id.relative_btn2);
}
}