一个很规范的自定义View实例:
1)继承View
public class CircleView extends View{
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private int mColor = Color.RED;
public CircleView(Context context){
super(context);
init();
}
public CircleView(Context context,AttributeSet attrs){
this(context,attrs,0);
}
public CircleView(Context context,AttributeSet attrs,int defStyleAttr){
super(context,attrs,defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.CircleView);
mColor=a.getColor(R.styleable.CircleView_circle_color,Color.RED);
a.recycle();
init();
}
private void init(){
mPaint.setColor(mColor);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpeceMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSpceSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpceSize = MeasureSpec.getSize(heightMeasureSpec);
if(widthSpecMode == MeasureSpec.AT_MOST && heightSpeceMode == MeasureSpec.AT_MOST){
setMeasuredDimension(200,200);
}else if(widthSpecMode == MeasureSpec.AT_MOST){
setMeasuredDimension(200,heightSpceSize);
}else if(heightSpeceMode == MeasureSpec.AT_MOST){
setMeasuredDimension(widthSpceSize,200);
}
}
@Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
final int paddingLeft = getPaddingLeft();
final int paddingTop = getPaddingTop();
final int paddintRight = getPaddingRight();
final int paddingBottom = getPaddingBottom();
int width = getWidth()- paddingLeft - paddintRight;
int height = getHeight() - paddingLeft - paddintRight;
int radius = Math.min(width,height) / 2;
canvas.drawCircle(paddingLeft + width / 2,paddingTop + height / 2,radius,mPaint);
}
}
2)继承ViewGroup
public class HorizontalScrollViewEx extends ViewGroup{
private static final String TAG = "HorizontalScrollViewEx";
private int mChildrenSize;
private int mChildWidth;
private int mChildIndex;
//分别记录上次滑动的坐标
private int mLastX = 0;
private int mLastY = 0;
//分别记录上次滑动的坐标(onInterceptTouchEvent)
private int mLastXIntecept = 0;
private int mLastYIntecept = 0;
private Scroller mScroller;
private VelocityTracker mVelocityTracker;
public HorizontalScrollViewEx(Context context){
super(context);
init();
}
public HorizontalScrollViewEx(Context context,AttributeSet attrs){
super(context,attrs);
init();
}
public HorizontalScrollViewEx(Context context,AttributeSet attrs,int defStyleAttr){
super(context,attrs,defStyleAttr);
init();
}
private void init(){
if(mScroller == null){
mScroller = new Scroller(getContext());
mVelocityTracker = VelocityTracker.obtain();
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event){
boolean intercepted = false;
int x =(int) event.getX();
int y =(int) event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:{
intercepted = false;
if(!mScroller.isFinished()){
mScroller.abortAnimation();
intercepted=true;
}
break;
}
case MotionEvent.ACTION_MOVE:{
int deltaX = x - mLastXIntecept;
int deltaY = y - mLastYIntecept;
if(Math.abs(deltaX)>Math.abs(deltaY)){
intercepted = true;
}else{
intercepted = false;
}
break;
}
case MotionEvent.ACTION_UP:{
intercepted = false;
break;
}
default:
break;
}
mLastX = x;
mLastY = y;
mLastXIntecept = x;
mLastYIntecept = y;
return intercepted;
}
@Override
public boolean onTouchEvent(MotionEvent event){
mVelocityTracker.addMovement(event);
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:{
if(!mScroller.isFinished()){
mScroller.abortAnimation();
}
break;
}
case MotionEvent.ACTION_MOVE:{
int deltaX = x - mLastX;
int deltaY = y - mLastY;
scrollBy(-deltaX,0);
break;
}
case MotionEvent.ACTION_UP:{
int scrollX = getScrollX();
mVelocityTracker.computeCurrentVelocity(1000);
float xVelocity = mVelocityTracker.getXVelocity();
if(Math.abs(xVelocity) >=50){
mChildIndex = xVelocity > 0 ? mChildIndex-1 : mChildIndex + 1;
}else{
mChildIndex = (scrollX + mChildWidth/2)/mChildWidth;
}
mChildIndex = Math.max(0,Math.min(mChildIndex,mChildrenSize -1));
int dx = mChildIndex * mChildWidth -scrollX;
smoothScrollBy(dx ,0);
mVelocityTracker.clear();
break;
}
default:
break;
}
mLastX = x;
mLastY = y;
return true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
int measuredWidth = 0;
int measureHeight = 0;
final int childCount = getChildCount();
measureChildren(widthMeasureSpec,heightMeasureSpec);
int widthSpaceSize = MeasureSpec.getSize(widthMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpceSize = MeasureSpec.getSize(heightMeasureSpec);
int heightSpeceMode = MeasureSpec.getMode(heightMeasureSpec);
if(childCount == 0){
setMeasuredDimension(0,0);
}else if(widthSpecMode == MeasureSpec.AT_MOST && heightSpeceMode == MeasureSpec.AT_MOST){
final View childView = getChildAt(0);
measuredWidth = childView.getMeasuredWidth() * childCount;
measureHeight = childView.getMeasureHeight();
setMeasuredDimension(measuredWidth,measureHeight);
}else if(heightSpeceMode == MeasureSpec.AT_MOST){
final View childView = getChildAt(0);
measureHeight =childView.getMeasureHeight();
setMeasuredDimension(widthSpaceSize,measureHeight);
}else if(widthSpecMode == MeasureSpec.AT_MOST){
final View childView = getChildAt(0);
measuredWidth = childView.getMeasuredWidth() * childCount;
setMeasuredDimension(measuredWidth,heightSpceSize);
}
}
@Override
protected void onLayout(boolean changed,int l,int t, int r,int b){
int childLeft = 0;
final int childCount = getChildCount();
mChildrenSize = childCount;
for(int i=0;i<childCount;i++){
final View childView = getChildAt(i);
if(childView.getVisibility() != View.GONE){
final int childWidth = childView.getMeasuredWidth();
mChildWidth = childWidth;
childView.layout(childLeft,0,childLeft + childWidth,childView.getMeasureHeight());
childLeft += childWidth;
}
}
}
private void smoothScrollBy(int dx,int dy){
mScroller.startScroll(getScrollX(),0,dx,0,500);
invalidate();
}
@Override
public void computeScroll(){
if(mScroller.computeScrollOffset()){
scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
postInvalidate();
}
}
@Override
protected void onDetachedFromWindow(){
mVelocityTracker.recycle();
super.onDetachedFromWindow();
}
}