Android 消息提示 小红点

声明:这个方案确实解决不了相对布局的问题,不好意思!


对于单一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);

	}

}




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值