聲明:這個方案确實解決不了相對布局的問題,不好意思!
對于單一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;
}
}
使用小紅點控件的demo:
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);
}
}