自定义控件粘性控件DOC.docx

上传人:b****6 文档编号:15572673 上传时间:2023-07-05 格式:DOCX 页数:28 大小:226.36KB
下载 相关 举报
自定义控件粘性控件DOC.docx_第1页
第1页 / 共28页
自定义控件粘性控件DOC.docx_第2页
第2页 / 共28页
自定义控件粘性控件DOC.docx_第3页
第3页 / 共28页
自定义控件粘性控件DOC.docx_第4页
第4页 / 共28页
自定义控件粘性控件DOC.docx_第5页
第5页 / 共28页
自定义控件粘性控件DOC.docx_第6页
第6页 / 共28页
自定义控件粘性控件DOC.docx_第7页
第7页 / 共28页
自定义控件粘性控件DOC.docx_第8页
第8页 / 共28页
自定义控件粘性控件DOC.docx_第9页
第9页 / 共28页
自定义控件粘性控件DOC.docx_第10页
第10页 / 共28页
自定义控件粘性控件DOC.docx_第11页
第11页 / 共28页
自定义控件粘性控件DOC.docx_第12页
第12页 / 共28页
自定义控件粘性控件DOC.docx_第13页
第13页 / 共28页
自定义控件粘性控件DOC.docx_第14页
第14页 / 共28页
自定义控件粘性控件DOC.docx_第15页
第15页 / 共28页
自定义控件粘性控件DOC.docx_第16页
第16页 / 共28页
自定义控件粘性控件DOC.docx_第17页
第17页 / 共28页
自定义控件粘性控件DOC.docx_第18页
第18页 / 共28页
自定义控件粘性控件DOC.docx_第19页
第19页 / 共28页
自定义控件粘性控件DOC.docx_第20页
第20页 / 共28页
亲,该文档总共28页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

自定义控件粘性控件DOC.docx

《自定义控件粘性控件DOC.docx》由会员分享,可在线阅读,更多相关《自定义控件粘性控件DOC.docx(28页珍藏版)》请在冰点文库上搜索。

自定义控件粘性控件DOC.docx

自定义控件粘性控件DOC

自定义控件:

粘性控件

GooView粘性控件

了解几何图形工具的用法

掌握画不规则图形的方法

应用场景:

未读提醒,效果图:

绘制一帧的效果

画一帧粘性控件的步骤分析

1.画一个固定圆

2.画一个拖拽圆

3.画中间连接部分

将中间连接部分水平放置,四个角的坐标定为固定值,分别标记上点的编号,矩形中心的点为控件点,画曲线时用

自定义一个GooView继承View

publicclassGooViewextendsView{

privatePaintpaint;

publicGooView(Contextcontext){

this(context,null);

}

publicGooView(Contextcontext,AttributeSetattrs){

this(context,attrs,0);

}

publicGooView(Contextcontext,AttributeSetattrs,intdefStyle){

super(context,attrs,defStyle);

//初始化画笔

paint=newPaint();

paint.setAntiAlias(true);

paint.setColor(Color.RED);

}

@Override

protectedvoidonDraw(Canvascanvas){

super.onDraw(canvas);

//画中间连接部分

Pathpath=newPath();

//跳到点1,默认为(0f,0f)

path.moveTo(250f,250f);

//从点1->点2画曲线

path.quadTo(150f,300f,50f,250f);

//从点2->点3画直线

path.lineTo(50f,350f);

//从点3->点4画曲线

path.quadTo(150f,300f,250f,350f);

canvas.drawPath(path,paint);

//画拖拽圆

canvas.drawCircle(90f,90f,16f,paint);

//画固定圆

canvas.drawCircle(150f,150f,12f,paint);

}

}

第20-30行用Path画中间曲线部分

第25行quadTo(x1,y1,x2,y2)方法可以画当前所在点到x2,y2间的一条曲线,x1,y1是当前点与x2,y2间的一个控件点,它的位置决定曲线弯曲的方向和弧度,将GooView显示到MainActivity中

publicclassMainActivityextendsActivity{

@Override

protectedvoidonCreate(BundlesavedInstanceState){

requestWindowFeature(Window.FEATURE_NO_TITLE);

super.onCreate(savedInstanceState);

setContentView(newGooView(this));

}

}

贝塞尔曲线

二阶贝塞尔曲线,三阶贝塞尔曲线

分别给拖拽圆,固定圆的圆心,半径,两个附着点命名,修改GooView的onDraw()方法

protectedvoidonDraw(Canvascanvas){

super.onDraw(canvas);

//固定圆的两个附着点

PointF[]mStickPoints=newPointF[]{

newPointF(250f,250f),newPointF(250f,350f)

};

//固定圆的两个附着点

PointF[]mDragPoints=newPointF[]{

newPointF(50f,250f),newPointF(50f,350f)

};

//控制点

PointFmControlPoint=newPointF(150f,300f);

//画中间连接部分

Pathpath=newPath();

//跳到点1,默认为(0f,0f)

path.moveTo(mStickPoints[0].x,mStickPoints[0].y);

//从点1->点2画曲线

path.quadTo(mControlPoint.x,mControlPoint.y,mDragPoints[0].x,mDragPoints[0].y);

//从点2->点3画直线

path.lineTo(mDragPoints[1].x,mDragPoints[1].y);

//从点3->点4画曲线

path.quadTo(mControlPoint.x,mControlPoint.y,mStickPoints[1].x,mStickPoints[1].y);

canvas.drawPath(path,paint);

//画拖拽圆

//拖拽圆圆心

PointFmDragCenter=newPointF(90f,90f);

//拖拽圆半径

floatmDragRadius=16f;

canvas.drawCircle(mDragCenter.x,mDragCenter.y,mDragRadius,paint);

//画固定圆

//固定圆圆心

PointFmStickCenter=newPointF(150f,150f);

//固定圆半径

floatmStickRadius=12f;

canvas.drawCircle(mStickCenter.x,mStickCenter.y,mStickRadius,paint);

}

第3-14行替换附着点及控制点

第30-40行替换拖拽圆及固定圆的圆心及半径

将替换后的变量转换成GooView的成员变量

//固定圆圆心

PointFmStickCenter=newPointF(150f,150f);

//固定圆半径

floatmStickRadius=12f;

//拖拽圆圆心

PointFmDragCenter=newPointF(90f,90f);

//拖拽圆半径

floatmDragRadius=16f;

//固定圆的两个附着点

PointF[]mStickPoints=newPointF[]{newPointF(250f,250f),

newPointF(250f,350f)};

//固定圆的两个附着点

PointF[]mDragPoints=newPointF[]{newPointF(50f,250f),

newPointF(50f,350f)};

//控制点

PointFmControlPoint=newPointF(150f,300f);

@Override

protectedvoidonDraw(Canvascanvas){

super.onDraw(canvas);

//画中间连接部分

Pathpath=newPath();

//跳到点1,默认为(0f,0f)

path.moveTo(mStickPoints[0].x,mStickPoints[0].y);

//从点1->点2画曲线

path.quadTo(mControlPoint.x,mControlPoint.y,mDragPoints[0].x,

mDragPoints[0].y);

//从点2->点3画直线

path.lineTo(mDragPoints[1].x,mDragPoints[1].y);

//从点3->点4画曲线

path.quadTo(mControlPoint.x,mControlPoint.y,mStickPoints[1].x,

mStickPoints[1].y);

canvas.drawPath(path,paint);

//画拖拽圆

canvas.drawCircle(mDragCenter.x,mDragCenter.y,mDragRadius,paint);

//画固定圆

canvas.drawCircle(mStickCenter.x,mStickCenter.y,mStickRadius,paint);

}

拖拽圆和固定圆的圆心和半径已知,角3的正弦值为两圆心纵坐标之差比上横坐标之差,则角3的角度可知,则角1可知,AB,AC的长度即可计算出来,mDragPoints[0]的坐标可以计算出来,同理其它三个附着点坐标也可知。

mControlPoint为两圆心连线的中点

几何图形工具

/**

*几何图形工具

*/

publicclassGeometryUtil{

/**

*Asmeaningofmethodname.

*获得两点之间的距离

*@paramp0

*@paramp1

*@return

*/

publicstaticfloatgetDistanceBetween2Points(PointFp0,PointFp1){

floatdistance=(float)Math.sqrt(Math.pow(p0.y-p1.y,2)+

Math.pow(p0.x-p1.x,2));

returndistance;

}

/**

*Getmiddlepointbetweenp1andp2.

*获得两点连线的中点

*@paramp1

*@paramp2

*@return

*/

publicstaticPointFgetMiddlePoint(PointFp1,PointFp2){

returnnewPointF((p1.x+p2.x)/2.0f,(p1.y+p2.y)/2.0f);

}

/**

*Getpointbetweenp1andp2bypercent.

*根据百分比获取两点之间的某个点坐标

*@paramp1

*@paramp2

*@parampercent

*@return

*/

publicstaticPointFgetPointByPercent(PointFp1,PointFp2,floatpercent){

returnnewPointF(evaluateValue(percent,p1.x,p2.x),

evaluateValue(percent,p1.y,p2.y));

}

/**

*根据分度值,计算从start到end中,fraction位置的值。

fraction范围为0->1

*@paramfraction

*@paramstart

*@paramend

*@return

*/

publicstaticfloatevaluateValue(floatfraction,Numberstart,Numberend){

returnstart.floatValue()+(end.floatValue()-start.floatValue())*fraction;

}

/**

*Getthepointofintersectionbetweencircleandline.

*获取通过指定圆心,斜率为lineK的直线与圆的交点。

*

*@parampMiddleThecirclecenterpoint.

*@paramradiusThecircleradius.

*@paramlineKTheslopeoflinewhichcrossthepMiddle.

*@return

*/

publicstaticPointF[]getIntersectionPoints(PointFpMiddle,floatradius,DoublelineK){

PointF[]points=newPointF[2];

floatradian,xOffset=0,yOffset=0;

if(lineK!

=null){

radian=(float)Math.atan(lineK);

xOffset=(float)(Math.sin(radian)*radius);

yOffset=(float)(Math.cos(radian)*radius);

}else{

xOffset=radius;

yOffset=0;

}

points[0]=newPointF(pMiddle.x+xOffset,pMiddle.y-yOffset);

points[1]=newPointF(pMiddle.x-xOffset,pMiddle.y+yOffset);

returnpoints;

}

}

利用几何图形工具类计算四个附着点坐标及控件点坐标

protectedvoidonDraw(Canvascanvas){

super.onDraw(canvas);

floatyOffset=mStickCenter.y-mDragCenter.y;

floatxOffset=mStickCenter.x-mDragCenter.x;

DoublelineK=null;

if(xOffset!

=0){

//xOffset分母不能为0

lineK=(double)(yOffset/xOffset);

}

//计算四个附着点

mDragPoints=GeometryUtil.getIntersectionPoints(mDragCenter,

mDragRadius,lineK);

mStickPoints=GeometryUtil.getIntersectionPoints(mStickCenter,

mStickRadius,lineK);

//一个控制点

mControlPoint=GeometryUtil.getMiddlePoint(mDragCenter,mStickCenter);

//画中间连接部分

Pathpath=newPath();

//跳到点1,默认为(0f,0f)

path.moveTo(mStickPoints[0].x,mStickPoints[0].y);

//从点1->点2画曲线

path.quadTo(mControlPoint.x,mControlPoint.y,mDragPoints[0].x,

mDragPoints[0].y);

//从点2->点3画直线

path.lineTo(mDragPoints[1].x,mDragPoints[1].y);

//从点3->点4画曲线

path.quadTo(mControlPoint.x,mControlPoint.y,mStickPoints[1].x,

mStickPoints[1].y);

canvas.drawPath(path,paint);

//画拖拽圆

canvas.drawCircle(mDragCenter.x,mDragCenter.y,mDragRadius,paint);

//画固定圆

canvas.drawCircle(mStickCenter.x,mStickCenter.y,mStickRadius,paint);

}

第3-17行计算四个附着点及控制点坐标

1.4计算固定圆半径

GooView重写onSizeChanged()方法,计算状态栏高度

@Override

protectedvoidonSizeChanged(intw,inth,intoldw,intoldh){

super.onSizeChanged(w,h,oldw,oldh);

//获取状态栏的高度,传入一个显示在屏幕上的view即可

statusBarHeight=Utils.getStatusBarHeight(this);

}

Utils.Java

publicclassUtils{

publicstaticToastmToast;

publicstaticvoidshowToast(ContextmContext,Stringmsg){

if(mToast==null){

mToast=Toast.makeText(mContext,"",Toast.LENGTH_SHORT);

}

mToast.setText(msg);

mToast.show();

}

/**

*获取状态栏高度

*

*@paramv

*@return

*/

publicstaticintgetStatusBarHeight(Viewv){

if(v==null){

return0;

}

Rectframe=newRect();

v.getWindowVisibleDisplayFrame(frame);

returnframe.top;

}

}

修改onDraw()方法

protectedvoidonDraw(Canvascanvas){

super.onDraw(canvas);

floatyOffset=mStickCenter.y-mDragCenter.y;

floatxOffset=mStickCenter.x-mDragCenter.x;

DoublelineK=null;

if(xOffset!

=0){

//xOffset分母不能为0

lineK=(double)(yOffset/xOffset);

}

//计算四个附着点

mDragPoints=GeometryUtil.getIntersectionPoints(mDragCenter,

mDragRadius,lineK);

mStickPoints=GeometryUtil.getIntersectionPoints(mStickCenter,

mStickRadius,lineK);

//一个控制点

mControlPoint=GeometryUtil.getMiddlePoint(mDragCenter,mStickCenter);

//移动画布

canvas.save();

canvas.translate(0,-statusBarHeight);

//画中间连接部分

Pathpath=newPath();

//跳到点1,默认为(0f,0f)

path.moveTo(mStickPoints[0].x,mStickPoints[0].y);

//从点1->点2画曲线

path.quadTo(mControlPoint.x,mControlPoint.y,mDragPoints[0].x,

mDragPoints[0].y);

//从点2->点3画直线

path.lineTo(mDragPoints[1].x,mDragPoints[1].y);

//从点3->点4画曲线

path.quadTo(mControlPoint.x,mControlPoint.y,mStickPoints[1].x,

mStickPoints[1].y);

canvas.drawPath(path,paint);

//画拖拽圆

canvas.drawCircle(mDragCenter.x,mDragCenter.y,mDragRadius,paint);

//画固定圆

canvas.drawCircle(mStickCenter.x,mStickCenter.y,mStickRadius,paint);

canvas.restore();

}

第18-20行把画布向上移动状态栏的高度,移动前需要保存一下当前状态,做完操作后需要恢复一下状态,由于在onTouchEvent()中用的是getRawX(),getRawY()获取的是相对屏幕的坐标,所以GooView画图操作时需要向上移到一个状态栏的高度才能刚好和手指重合拖拽圆跟随手指移动时,随着拖拽与固定圆的距离的变大,固定圆的半径越来越小

//允许的最大距离

floatfarestDistance=80f;

/**

*通过两圆圆心的距离,计算固定圆的半径

*@return

*/

privatefloatcomputeStickRadius(){

//通过几何图形工具类可以计算出两圆圆心的距离,distance是可以大于80f;

floatdistance=GeometryUtil.getDistanceBetween2Points(mDragCenter,mStickCenter);

//需要的是0.0f->1.0f的值,所在大于80f让distance等于80f

distance=Math.min(farestDistance,distance);

floatpercent=distance/farestDistance;

//需要固定圆心半径在12f->3f间变化,可以利用类型估值器

returnevaluate(percent,mStickRadius,mStickRadius*0.25f);

}

//FloatEvaluator.java中拷贝

publicFloatevaluate(floatfraction,NumberstartValue,NumberendValue){

floatstartFloat=startValue.floatValue();

returnstartFloat+fraction*(endValue.floatValue()-startFloa

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2