1.设置padding
Margin属性不需要定义,padding属性需要自己在onDraw()方法
里面把padding考虑进去
直接设置padding是没有效果的,如图,设置了Top和Left的padding。
需要在你的onDraw()方法
里面设置padding
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int paddingLeft = getPaddingLeft();
int paddingRight = getPaddingRight();
int paddingTop = getPaddingTop();
int paddingBottom = getPaddingBottom();
int width=getWidth()-paddingLeft-paddingRight;
int height=getHeight()-paddingTop-paddingBottom;
canvas.drawCircle(width/2+paddingLeft,height/2+paddingTop,width/2,paint);
}
我这也不对,只是有效果了,先不管了。
2.View的滑动
通过重写onTouchEvent()方法,然后用 layout()方法来移动。
@Override
public boolean onTouchEvent(MotionEvent event) {
int x= (int) event.getX();
int y= (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN: //记录最开始的位置
lastX=x;
lastY=y;
break;
case MotionEvent.ACTION_MOVE: //算出偏移量,然后再用layout移动view
int offestX=x-lastX;
int offestY=y-lastY;
layout(getLeft()+offestX,getTop()+offestY,getRight()+offestX,getBottom()+offestY);
break;
}
return true;
//返回true 和 false的效果是有区别的:
//setOnTouchListener 单独使用的时候返回值需要为true,这样才能保证移动的时候能后获取相应的监听,而非一次监听(即每次只有一个按下的事件)
//setOnTouchListener 和 setOnClickListener 同时使用时,onTouch 的返回值要设为 false,这样既可以保证按下移动抬起事件可以被监听,并且点击事件也会被监听。
}
效果图:
还有好几种其他的滑动方式
3.自定义属性
在values目录下创建attrs.xml
//.....更多你想要的属性
然后在RectView的构造方法中解析这些属性
public RectView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.RectView);
color=typedArray.getColor(R.styleable.RectView_color_pc,Color.RED);
typedArray.recycle();
init(); //在xml中调用的,所以在这里初始化
}
4.onMeasure方法
这个方法主要是实现wrap_content属性
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int withSpecMode=MeasureSpec.getMode(widthMeasureSpec);
int heightSpecMode=MeasureSpec.getMode(heightMeasureSpec);
int withSpecSize=MeasureSpec.getSize(widthMeasureSpec);
int heightSpecSize=MeasureSpec.getSize(heightMeasureSpec);
if (withSpecMode== ViewGroup.LayoutParams.WRAP_CONTENT &&heightSpecMode==ViewGroup.LayoutParams.WRAP_CONTENT){
setMeasuredDimension(200,200);
}
if (withSpecMode==ViewGroup.LayoutParams.WRAP_CONTENT){
setMeasuredDimension(200,heightSpecSize);
}
if (heightSpecMode==ViewGroup.LayoutParams.WRAP_CONTENT){
setMeasuredDimension(withSpecSize,200);
}
}
若果把判断条件改为withSpecMode==MeasureSpec.AT_MOST
,存在一定的错误
,详解见为什么你的自定义View wrap_content不起作用?文末第5点的特别注意。