Andriod 學習筆記之八 自定義view實現圓圈標記

目的

實現一個自定義的view,能夠在這個圓圈裏面實現顯示數子,數字居中顯示


佈局文件

在佈局文件中添加
<span style="white-space:pre">	</span><com.android.mms.ui.TctUnReadIcon
                android:id="@+id/unread_icon" 
                android:layout_width="18dp"
                android:layout_height="18dp"
                android:layout_alignParentTop="true"
                android:layout_alignParentRight="true"
                android:layout_marginTop="5dp"
                android:layout_marginRight="5dp"
                android:visibility="gone"
                />

自定義控件的實現類

下面這個類 是自定義控件的實現類

<pre name="code" class="java">public class TctUnReadIcon extends View {

	private String mUnReadCount = "";
	private Paint mTextPaint;
	private Paint mCirclePaint;
	private Rect mRectBound;
	private int mScreenWidth;
	private int mScreenHeight;
	
	public TctUnReadIcon(Context context, AttributeSet attrs) {
		super(context, attrs);
		
		init();
	}
	
    private void init() {
	//通過MessageUtils這個類我們可以得到手機屏幕的大小 ,這裏的480,800指的是開發時手機的屏幕分辨率,
	//因爲通過paint.setTextSize()設置字體大小的時候,用的是px,而我們一般設置字體的時候用sp,dp ,這個在下面會講到
        mScreenWidth = MessageUtils.getScreenWidth();
        mScreenHeight = MessageUtils.getScreenHeight();
        float ratioWidth = (float)mScreenWidth / 480;  
        float ratioHeight = (float)mScreenHeight / 800;  
        float RATIO = Math.min(ratioWidth, ratioHeight);    
        
        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setTextSize((int)(15 * RATIO)); //這裏經過實際的調試實現的是15dp
        mTextPaint.setColor(Color.WHITE);
        mTextPaint.setStyle(Paint.Style.FILL);
        
        mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mCirclePaint.setColor(Color.RED);
        mCirclePaint.setStyle(Paint.Style.FILL);
        
        mRectBound = new Rect();
        
        Log.d("yyyyy", " iconSize = " + ((int)(15 * RATIO)));

	}

	@Override
    protected void onDraw(Canvas canvas) {
    	super.onDraw(canvas);
    	
    	int width = getWidth();
    	int height = getHeight();
    	Log.d("yyyyy", "width = " + getWidth() + " ,height = " + getHeight());
    	int circleRadius = Math.min(width, height) / 2;
    	
        //繪製圓		
    	canvas.drawCircle(width / 2, height / 2, circleRadius , mCirclePaint);
	//在圓上繪製數字    	
	mTextPaint.getTextBounds(mUnReadCount, 0, mUnReadCount.length(),mRectBound);
    	canvas.drawText(mUnReadCount, width / 2 - mRectBound.width() / 2 - 1,
				height / 2 + mRectBound.height() / 2, mTextPaint);
    	Log.d("yyyyy", "drawText  width = " + (width / 2 - mRectBound.width() / 2) + " ," +
				"height = " + (height / 2 + mRectBound.height() / 2)   );
    }
	//設置中間顯示的數字
	public void setmUnReadCount(String mUnReadCount) {
		this.mUnReadCount = mUnReadCount;
		
		mTextPaint.getTextBounds(mUnReadCount, 0, mUnReadCount.length(),mRectBound);
		invalidate();
	}
}


在上面用到了一個MessageUtil.java類,在這個類裏面,得到屏幕信息的操作,這樣增強了屏幕的適配性
public class MessageUtils {
    private static int mScreenWidth; 
    private static int mScreenHeight; 

    public static void setScreenWidth(int screenWidth){
    	mScreenWidth = screenWidth ;
    }
    
    public static void setScreenHeight(int screenHeight){
    	mScreenHeight = screenHeight;
    }
    
    public static int getScreenWidth(){
    	return mScreenWidth;
    }
    
    public static int getScreenHeight(){
    	return mScreenHeight;
    }
}

要調用上面的類,需要在mainactivity.java 裏面調用
        DisplayMetrics displayMetrics = new DisplayMetrics();  
        this.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int screenWidth = displayMetrics.widthPixels;  
        int screenHeight = displayMetrics.heightPixels; 
        MessageUtils.setScreenWidth(screenWidth);
        MessageUtils.setScreenHeight(screenHeight); 

然後,在這個控件顯示的頁面調用setmUnReadCount()方法,不然控件裏面的數字會顯示爲空


效果如下圖中的紅色圓圈
紅色圓圈


附錄學習資料


android中dip、dp、px、sp和屏幕密度

    
1. dip: device independent pixels(設備獨立像素). 不同設備有不同的顯示效果,這個和設備硬件有關,一般我們爲了支持WVGA、HVGA和QVGA 推薦使用這    這個,不依賴像素。 
   這裏要特別注意dip與屏幕密度有關,而屏幕密度又與具體的硬件有關,硬件設置不正確,有可能導致dip不能正常顯示。在屏幕密度爲160的顯示屏上,1dip=1px,有時候可能你的屏幕分辨率很大如480*800,但是屏幕密度沒有正確設置比如說還是160,那麼這個時候凡是使用dip的都會顯示異常,基本都是顯示過小。 
     dip的換算: 
           dip(value)=(int) (px(value)/1.5 + 0.5) 
2. dp: 很簡單,和dip是一樣的。 
3. px: pixels(像素),不同的設備不同的顯示屏顯示效果是相同的,這是絕對像素,是多少就永遠是多少不會改變。 
4.  sp: scaled pixels(放大像素). 主要用於字體顯示best for textsize。 

5. dpi(dot per inch):屏幕每英寸打印點數,每英寸多少打印點,打印的時候對像素密度的表達
6. ppi(dot per pixels):屏幕上每英寸上的像素點數
7. density:density表示每英寸有多少個顯示點(邏輯值),它的單位是ppi



備註: 根據google的推薦,像素統一使用dip,字體統一使用sp  
舉個例子區別px和dip:
px就是像素,如果用px,就會用實際像素畫,比個如吧,用畫一條長度爲240px的橫線,在480寬的模擬器上看就是一半的屏寬,而在320寬的模擬器上看就是2/3的屏寬了。
而dip,就是把屏幕的高分成480分,寬分成320分。比如你做一條160dip的橫線,無論你在320還480的模擬器上,都是一半屏的長度。

public static int dip2px(Context context, float dipValue){ 
                final float scale = context.getResources().getDisplayMetrics().density; 
                return (int)(dipValue * scale + 0.5f); 
        } 
        
    public static int px2dip(Context context, float pxValue){ 
                final float scale = context.getResources().getDisplayMetrics().density; 
                return (int)(pxValue / scale + 0.5f); 
        }















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章