天天看點

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);

	}

}