編輯:關於Android編程
圓角控件常用於頭像,按鈕,圖標等,用途十分廣泛,而且常常配合board使用。

在IOS中,UIVIew的CALayer層已經提供了圓角和board的方法,所以圓角控件的制作非常簡單,只需要類似以下簡單代碼即可實現:
view.layer.cornerRadius = 20;
view.layer.borderColor = [UIColor yellowColor].CGColor;
view.layer.borderWidth = 10;
view.clipsToBounds = YES;
<com.me.obo.circleboardimage.circleview.roundimageview android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/head" attr:border_width="3dp" attr:corner_y="40dp" attr:corner_x="40dp" attr:border_color="#FFFFFF"></com.me.obo.circleboardimage.circleview.roundimageview>
下面就介紹如何實現這樣一個RoundImageView
在Android中,遮罩功能非常強大,可以用於生成兩張圖片相互截取的結果。

具體參數和遮罩的效果可以見鏈接: Android 實現遮罩
在RoundImageView中,遮罩用於清除控件外圈的內容,從而獲取到圓角的效果。這裡的思路是先獲取到控件本身所繪制的圖片,之後獲取圓角矩形遮罩圖片,然後兩個圖片采用DST_IN遮罩模式來截取中間的遮罩效果,即:

代碼實現如下:
// 獲取imageview原先的圖片
super.onDraw(mDestCanvas);
// 創建矩形,表示圓角矩形
if (mRoundRectClip == null) {
mRoundRectClip = new RectF(mBorderValue, mBorderValue, getWidth() - mBorderValue, getHeight() - mBorderValue);
}
// 繪制圓角矩形
mSrcCanvas.drawRoundRect(mRoundRectClip,mCornerXValue,mCornerYValue,mNomalPaint);
// 使用遮罩畫筆扣除原圖中的圓角矩形外面的部分
mDestCanvas.drawBitmap(mSrcBitmap,0,0,mPaintClip);
在獲取到遮罩處理的圖片之後,為其添加board將會變得容易,也就是在外圈繪制出一個帶有寬度的圓即可。

代碼實現如下:
// 創建board的矩形
if (mRoundRectBorder == null) {
mRoundRectBorder = new RectF(mBorderValue / 2, mBorderValue / 2, getWidth() - mBorderValue / 2, getHeight() - mBorderValue / 2);
}
// 繪制board
mDestCanvas.drawRoundRect(mRoundRectBorder, mCornerXValue, mCornerYValue, mPaintBoard);
整個RoundImageView完整的代碼如下:
package com.me.obo.circleboardimage.circleview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.me.obo.circleboardimage.R;
/**
* Created by obo on 16/5/11.
* Email:obo1993@gmail.com
* Git:https://github.com/OboBear
* Blog:http://blog.csdn.net/leilba
*/
public class RoundImageView extends ImageView {
private float mCornerXValue ;
private float mCornerYValue ;
private float mBorderValue ;
private int mBorderColor ;
public RoundImageView(Context context, AttributeSet attrs) {
super(context, attrs);
// 獲取自定義參數
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.RoundImageView);
// board顏色
mBorderColor = typedArray.getColor(R.styleable.RoundImageView_border_color,Color.argb(0,0,0,0));
// 獲取X方向曲率
mCornerXValue = typedArray.getDimension(R.styleable.RoundImageView_corner_x,0);
// 獲取Y方向曲率
mCornerYValue = typedArray.getDimension(R.styleable.RoundImageView_corner_y,0);
// board寬
mBorderValue = typedArray.getDimension(R.styleable.RoundImageView_border_width,0);
// 用完需要recycle
typedArray.recycle();
initPaints();
}
private void initPaints() {
// 創建普通畫筆
if (mNomalPaint == null) {
mNomalPaint = new Paint();
}
// 創建遮罩畫筆
if (mPaintClip == null) {
mPaintClip = new Paint();
mPaintClip.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaintClip.setAntiAlias(true);
}
// 創建board的畫筆
if (mPaintBoard == null) {
mPaintBoard = new Paint();
mPaintBoard.setColor(mBorderColor);
mPaintBoard.setStyle(Paint.Style.STROKE);
mPaintBoard.setStrokeWidth(mBorderValue);
}
}
Bitmap mDestBitmap;
Bitmap mSrcBitmap;
Canvas mDestCanvas;
Canvas mSrcCanvas;
Paint mPaintClip;
Paint mNomalPaint;
Paint mPaintBoard;
RectF mRoundRectClip;
RectF mRoundRectBorder;
@Override
protected void onDraw(Canvas canvas) {
// 創建遮罩圖片和畫布
if (mDestBitmap == null) {
mDestBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
mSrcBitmap = Bitmap.createBitmap(getWidth(),getHeight(), Bitmap.Config.ARGB_8888);
mDestCanvas = new Canvas(mDestBitmap);
mSrcCanvas = new Canvas(mSrcBitmap);
}
// 獲取imageview原先的圖片
super.onDraw(mDestCanvas);
// 創建矩形,表示圓角矩形
if (mRoundRectClip == null) {
mRoundRectClip = new RectF(mBorderValue, mBorderValue, getWidth() - mBorderValue, getHeight() - mBorderValue);
}
// 繪制圓角矩形
mSrcCanvas.drawRoundRect(mRoundRectClip,mCornerXValue,mCornerYValue,mNomalPaint);
// 使用遮罩畫筆扣除原圖中的圓角矩形外面的部分
mDestCanvas.drawBitmap(mSrcBitmap,0,0,mPaintClip);
// 創建board的矩形
if (mRoundRectBorder == null) {
mRoundRectBorder = new RectF(mBorderValue / 2, mBorderValue / 2, getWidth() - mBorderValue / 2, getHeight() - mBorderValue / 2);
}
// 繪制board
mDestCanvas.drawRoundRect(mRoundRectBorder, mCornerXValue, mCornerYValue, mPaintBoard);
// 繪制最終的圓角帶有board的圖
canvas.drawBitmap(mDestBitmap,0,0,mNomalPaint);
}
}
可能有人要問,圓角彎曲度和board的參數是如何傳遞到RoundImageView裡的。實際上,這裡采用了自定義Attribute的方式,該操作需要到res/values 目錄下創建 attr.xml 文件,在裡面寫上自定義的參數名稱以及類型:
<resources>
<declare-styleable name="RoundImageView">
<attr name="border_width" format="dimension">
<attr name="border_color" format="color">
<attr name="corner_x" format="dimension">
<attr name="corner_y" format="dimension">
</attr></attr></attr></attr></declare-styleable>
</resources>
public RoundImageView(Context context, AttributeSet attrs) {
super(context, attrs);
// 獲取自定義參數
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.RoundImageView);
// board顏色
mBorderColor = typedArray.getColor(R.styleable.RoundImageView_border_color,Color.argb(0,0,0,0));
// 獲取X方向曲率
mCornerXValue = typedArray.getDimension(R.styleable.RoundImageView_corner_x,0);
// 獲取Y方向曲率
mCornerYValue = typedArray.getDimension(R.styleable.RoundImageView_corner_y,0);
// board寬
mBorderValue = typedArray.getDimension(R.styleable.RoundImageView_border_width,0);
// 用完需要recycle
typedArray.recycle();
initPaints();
}
xmlns:attr="http://schemas.android.com/apk/res-auto"最後,在layout裡面調用RoundImageView的代碼非常簡潔:
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:attr="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/darker_gray" android:orientation="vertical">
<com.me.obo.circleboardimage.circleview.roundimageview android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/head" attr:border_width="3dp" attr:corner_y="40dp" attr:corner_x="40dp" attr:border_color="#FFFFFF">
<com.me.obo.circleboardimage.circleview.roundimageview android:layout_width="180dp" android:layout_height="180dp" android:src="@drawable/head" attr:border_width="2dp" attr:corner_y="40dp" attr:corner_x="40dp" attr:border_color="#FF0000" android:scaletype="fitXY">
</com.me.obo.circleboardimage.circleview.roundimageview></com.me.obo.circleboardimage.circleview.roundimageview></linearlayout>
效果如下:

Android網絡編程(總結)
概述首先,應該了解的幾個問題:1)Android平台網絡相關API接口a) java.net.*(標准Java接口) java.net.*提供與聯網有關的類,包
分析Android App中內置換膚功能的實現方式
Android平台api沒有特意為換膚提供一套簡便的機制,這可能是外國的軟件更注重功能和易用,不流行換膚。系統不提供直接支持,只能自行研究。 換膚,可以認為是動態替換資源
android 焦點事件 觸發順序
整個布局將觸發的方法如下:點擊TextView1 時,執行循環一次後。最後方法將不再向下傳遞。直接交個 Activity執行04-28 16:22:09.509: I/S
OSG for Android新手教程系列(二)——項目配置
在上一篇教程中,主要介紹了如何把OSG源代碼編譯成為能夠在Android項目下使用的函數庫。在這一篇教程中,我將針對如何在自己的Android項目中配置OSG函數庫進行詳