android 自定义View

一、view的测量

1.测量的模式:

EXACTLY :精确值模式,当把空间的layout_width属性或者layout_height的属性设置为具体的数值时,或者指定为match_parent时候,系统就是使用的EXACTLY 模式;

AT_MOST: 最大值模式,当空间的layout_width属性或者layout_height属性指定为wrap_content时候,控件大小跟着控件的内容变化而变化,此时控件的尺寸只要不超过父控件允许的最大尺寸即可。

UNSPECIFIED: 这个属性比较奇怪,不指定其测量大小模式,view想多大就多大,通常情况下只有在绘制自定义view的时候才会使用

2.简单演示如何进行view的测量

1.自定义一个类继承自View

publicclassoneextendsView{publicone(Contextcontext){super(context);}publicone(Contextcontext,@NullableAttributeSetattrs){super(context,attrs);}publicone(Contextcontext,@NullableAttributeSetattrs,intdefStyleAttr){super(context,attrs,defStyleAttr);}//重写onMeasure方法来进行测量@OverrideprotectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec));}//测量高度privateintmeasureHeight(intheightMeasureSpec){//第一步,从MeasureSpec对象中提取出具体的测量模式和大小intspecMode=MeasureSpec.getMode(heightMeasureSpec);intspecSize=MeasureSpec.getSize(heightMeasureSpec);intresult=0;//检测是否是精确值模式if(specMode==MeasureSpec.EXACTLY){result=specSize;}else{//如果不是就自己设定result=200;if(specMode==MeasureSpec.AT_MOST){result=Math.min(result,specSize);}}returnresult;}privateintmeasureWidth(intwidthMeasureSpec){intspecMode=MeasureSpec.getMode(widthMeasureSpec);intspecSize=MeasureSpec.getSize(widthMeasureSpec);intresult=0;if(specMode==MeasureSpec.EXACTLY){result=specSize;}else{result=200;if(specMode==MeasureSpec.AT_MOST){result=Math.min(result,specSize);}}returnresult;}}

2.新建一个xml文件来作为自定义view的载体

<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><Viewandroid:layout_width="400px"android:layout_height="400px"android:background="#00ff0f"/></LinearLayout>

3.在main活动的xml文件下添加自定义的控件

<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"android:orientation="vertical"><com.example.customize_learning.learning.oneandroid:layout_width="400px"android:layout_height="400px"/></LinearLayout>

主要是进行测量,测量的主要步骤就是重写onMeasure方法,在代码中有很详细的注释

二、view的绘制

简单来说就是继承view之后再重写onDraw方法,并在Canvas对象上来绘制需要的图形

以绘制一个闪光的文字作为例子

1.新建一个类及其xml文件

publicclassMyTextViewextendsTextView{privateintmViewWidth;privatePaintmPaint;privateLinearGradientmLinearGradient;privateMatrixmGradientMatrix;privateintmTranslate;publicMyTextView(Contextcontext){super(context);}publicMyTextView(Contextcontext,@NullableAttributeSetattrs){super(context,attrs);}@OverrideprotectedvoidonSizeChanged(intw,inth,intoldw,intoldh){super.onSizeChanged(w,h,oldw,oldh);mPaint=newPaint();if(mViewWidth==0){mViewWidth=getMeasuredWidth();if(mViewWidth>0){mPaint=getPaint();/**

                * LinearGradient构造方法中的参数int[] color:

                * 第一个元素:发光字体闪过后所显示的字体颜色,这里给定与第三个元素一样

                * 第二个元素:字体发光的颜色

                * 第三个元素:原字体显示的颜色

                *

                * mViewWidth:设置发光的宽度

                * */mLinearGradient=newLinearGradient(0,0,mViewWidth,0,newint[]{0x22ffffff,0xffffffff,0x22ffffff},null,Shader.TileMode.CLAMP);mPaint.setShader(mLinearGradient);//创建矩形mGradientMatrix=newMatrix();}}}@OverrideprotectedvoidonDraw(Canvascanvas){super.onDraw(canvas);if(mGradientMatrix!=null){mTranslate+=mViewWidth/5;if(mTranslate>mViewWidth*2){mTranslate=-mViewWidth;}mGradientMatrix.setTranslate(mTranslate,0);mLinearGradient.setLocalMatrix(mGradientMatrix);//控制闪过的时间postInvalidateDelayed(80);}}}

<?xml version="1.0" encoding="utf-8"?><FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="我是一个会闪烁的TextView"/></FrameLayout>

2.将自定义控件添加到主活动的xml文件下面

<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"android:orientation="vertical"><com.example.customize_learning.learning.MyTextViewandroid:layout_height="wrap_content"android:layout_width="wrap_content"android:layout_marginTop="30dp"/></LinearLayout>

三、组合自定义控件

1.先建一个类,因为是组合控件,使其继承自RelativeLayout

2建一个xml文件

<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"android:layout_marginLeft="35dp"><Buttonandroid:id="@+id/plus_btn"android:layout_width="100dp"android:layout_height="wrap_content"android:textSize="18sp"android:background="@drawable/selector_left"android:text="+"></Button><EditTextandroid:id="@+id/values_edt"android:gravity="center"android:layout_gravity="center"android:layout_width="100dp"android:layout_height="wrap_content"android:text="0"/><Buttonandroid:id="@+id/minus_btn"android:background="@drawable/selector_right"android:layout_width="100dp"android:text="-"android:textSize="18sp"android:layout_height="wrap_content"></Button></LinearLayout></LinearLayout>

3.设置按钮按下和松开时候不同的效果

(1)设置左右两边按钮的自定义背景(按下时)

左边

<?xml version="1.0" encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><!--纯色填充--><solidandroid:color="#DFE8DF"/><!--设置圆角--><cornersandroid:bottomLeftRadius="10dp"android:topLeftRadius="10dp"/><!--渐变色--><gradientandroid:startColor="#EC1426"android:angle="270"android:centerColor="#C64B7C"android:endColor="#71363D"android:type="linear"/></shape>

右边

<?xml version="1.0" encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><solidandroid:color="#DFE8DF"/><cornersandroid:bottomRightRadius="10dp"android:topRightRadius="10dp"/><!--渐变色--><gradientandroid:startColor="#EC1426"android:angle="270"android:centerColor="#C64B7C"android:endColor="#71363D"android:type="linear"/></shape>

(2)设置不触碰时左右两边按钮的自定义背景

左边

<?xml version="1.0" encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><!--纯色填充--><solidandroid:color="#DFE8DF"/><!--设置圆角--><cornersandroid:bottomLeftRadius="10dp"android:topLeftRadius="10dp"/><!--渐变色--><gradientandroid:startColor="#14EC14"android:angle="270"android:centerColor="#4BC64B"android:endColor="#367143"android:type="linear"/></shape>>

右边

<?xml version="1.0" encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><solidandroid:color="#DFE8DF"/><cornersandroid:bottomRightRadius="10dp"android:topRightRadius="10dp"/><!--渐变色--><gradientandroid:startColor="#14EC14"android:angle="270"android:centerColor="#4BC64B"android:endColor="#367143"android:type="linear"/></shape>

(3)设置一个选择器,实现按下和松开展示不同的背景

左边

<?xml version="1.0" encoding="utf-8"?><selectorxmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:state_pressed="true"android:drawable="@drawable/shape_number_btn_bg_left_presses"/><itemandroid:drawable="@drawable/shape_number_btn_bg_left"/></selector>

右边

<?xml version="1.0" encoding="utf-8"?><selectorxmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:state_pressed="true"android:drawable="@drawable/shape_number_btn_bg_right_pressed"/><itemandroid:drawable="@drawable/shape_number_btn_bg_right"/></selector>

4.把自定义控件添加到主活动里边去

<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"android:orientation="vertical"><com.example.customize_learning.customview.InputNumberViewandroid:id="@+id/input_number"android:layout_height="100dp"android:layout_width="match_parent"/></LinearLayout>

5.在建的那个类中填写代码

packagecom.example.customize_learning.customview;importandroid.content.Context;importandroid.os.Build;importandroid.util.AttributeSet;importandroid.view.LayoutInflater;importandroid.view.View;importandroid.widget.EditText;importandroid.widget.RelativeLayout;importandroid.widget.TextView;importandroidx.annotation.RequiresApi;importcom.example.customize_learning.R;publicclassInputNumberViewextendsRelativeLayout{privateintmCurrentNumber=0;privateViewaddBtn;privateEditTextvalueEdt;privateViewminBtn;privateOnNumberChangemOnNumberChange=null;publicInputNumberView(Contextcontext){this(context,null);}publicInputNumberView(Contextcontext,AttributeSetattrs){this(context,attrs,0);}publicInputNumberView(Contextcontext,AttributeSetattrs,intdefStyleAttr){super(context,attrs,defStyleAttr);//绑定布局initView(context);//处理事件setEvent();}privatevoidsetEvent(){//实现值的增加addBtn.setOnClickListener(newOnClickListener(){@OverridepublicvoidonClick(Viewv){mCurrentNumber++;updateValue();}});//实现值的减少minBtn.setOnClickListener(newOnClickListener(){@OverridepublicvoidonClick(Viewv){mCurrentNumber--;updateValue();}});}//数据的更新privatevoidupdateValue(){valueEdt.setText(String.valueOf(mCurrentNumber));}privatevoidinitView(Contextcontext){//添加布局Viewview=LayoutInflater.from(context).inflate(R.layout.input_value_layout,this,false);addView(view);addBtn=this.findViewById(R.id.plus_btn);valueEdt=this.findViewById(R.id.values_edt);minBtn=this.findViewById(R.id.minus_btn);}publicintgetNumber(){returnmCurrentNumber;}publicvoidsetNumber(intmCurrentNumber){this.mCurrentNumber=mCurrentNumber;this.updateValue();}//暴露接口publicvoidSetOnNumberChange(OnNumberChangeonNumberChange){this.mOnNumberChange=onNumberChange;}publicinterfaceOnNumberChange{voidonNumberChange(intvalue);}}

里边代码很详尽,包含了暴露接口、处理事件的过程

6.在主活动java文件下处理事件

publicclassMainActivityextendsAppCompatActivityimplementsInputNumberView.OnNumberChange{publicstaticfinalStringTAG="MainActivity";@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);InputNumberViewinputNumberView=this.findViewById(R.id.input_number);inputNumberView.SetOnNumberChange(this);}//调用接口处理事件@OverridepublicvoidonNumberChange(intvalue){Log.d(TAG,"current value is == > "+value);}}

四、获取自定义view的属性

1.在values文件下面新建一个attrs的文件

<?xml version="1.0" encoding="utf-8"?><resources><declare-styleablename="InputNumberView"><attrname="max"format="integer"/><attrname="min"format="integer"/><attrname="step"format="integer"/><attrname="disable"format="boolean"/><attrname="btnColor"format="reference"/><attrname="valueSize"format="integer"/></declare-styleable></resources>

Integer,比如说行数,TextView的maxLine,就是Integer类型

enum,枚举类型,比如说gravity,left,top,bottom,center,right这些是枚举类型

boolean,布尔类型,比如说layout_alignParentRight

dimension,尺寸比如说size,margin_left这些,单位为px,dp,sp这些

color,这个大家都清楚了,颜色嘛,比如说background,比如说textColor

flags,标记,比如说我们学习activity声明周期时的configChanges

float,浮点数,也就是小数,比如说,透明度alpha

fraction,百分数,比如说动画的开始位置,fromDx

refrence,引用,比如说background,src,有同学可能有疑问了,background可以是color又可以是refrence,怎么整呢? 其实是可以多个的哈,比如说:name=“switch_time” format=“integer|float”,可以是Integer类型,或者float类型

string,这个最简单了,比如说text

2.获取属性

publicInputNumberView(Contextcontext,AttributeSetattrs,intdefStyleAttr){super(context,attrs,defStyleAttr);//获取相关属性initAttrs(context,attrs);//绑定布局initView(context);//处理事件setEvent();}//获取相关属性privatevoidinitAttrs(Contextcontext,AttributeSetattrs){typedArray=context.obtainStyledAttributes(attrs,R.styleable.InputNumberView);mMax=typedArray.getInt(R.styleable.InputNumberView_max,0);mMin=typedArray.getInt(R.styleable.InputNumberView_min,0);mStep=typedArray.getInt(R.styleable.InputNumberView_step,0);mValue=typedArray.getInt(R.styleable.InputNumberView_valueSize,0);mDisable=typedArray.getBoolean(R.styleable.InputNumberView_disable,false);typedArray.getResourceId(R.styleable.InputNumberView_btnColor,-1);Log.d(TAG,"mMax === >: "+mMax);Log.d(TAG,"mMin === >: "+mMin);Log.d(TAG,"mStep === >: "+mStep);Log.d(TAG,"mValue === >: "+mValue);Log.d(TAG,"mDisable === >: "+mDisable);typedArray.recycle();}

3.在引入该自定义控件的xml文件下使用属性

<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:hsk="http://schemas.android.com/apk/res-auto"tools:context=".MainActivity"android:orientation="vertical"><com.example.customize_learning.customview.InputNumberViewandroid:id="@+id/input_number"android:layout_height="match_parent"android:layout_width="match_parent"hsk:max="30"hsk:min="-30"hsk:step="5"hsk:disable="false"hsk:valueSize="15"hsk:btnColor="@drawable/selector_left"/></LinearLayout>

五、自定义viewgroup

1.首先创建一个类继承自viewgroup,实现方法

publicclassFlowLayoutextendsViewGroup{publicFlowLayout(Contextcontext){this(context,null);}publicFlowLayout(Contextcontext,AttributeSetattrs){this(context,attrs,0);}publicFlowLayout(Contextcontext,AttributeSetattrs,intdefStyleAttr){super(context,attrs,defStyleAttr);}@OverrideprotectedvoidonLayout(booleanchanged,intl,intt,intr,intb){}}

2.获取相关属性

在values文件夹下面新建一个attrs文件

<?xml version="1.0" encoding="utf-8"?><resources><declare-styleablename="Flowlayout"><attrname="InputNumberView_max"format="integer"/><attrname="itemHorizontalMargin"format="dimension"/><attrname="itemVerticalMargin"format="dimension"/><attrname="textMaxLine"format="integer"/><attrname="textColor"format="color"/><attrname="borderColor"format="color"/><attrname="borderRadius"format="dimension"/></declare-styleable></resources>

在该类下面获取相关属性

publicclassFlowLayoutextendsViewGroup{publicstaticfinalintDEFAULT_LINE=3;publicstaticfinalintDEFAULT_HORZONTAL_MARGIN=5;publicstaticfinalintDEFAULT_VERTIAL_MARGIN=5;publicstaticfinalintDEFAULT_TEXT_MAX_LENGTH=20;publicstaticfinalintDEFAULT_BORDER_RADIUS=20;privateTypedArraytypedArray;privateintanInt;privatefloathorizontalMargin;privatefloatverticalMargin;privateintmMaxLine;privateinttextcolor;privateintborderradius;privateList<String>mList=null;publicFlowLayout(Contextcontext){this(context,null);}publicFlowLayout(Contextcontext,AttributeSetattrs){this(context,attrs,0);}publicFlowLayout(Contextcontext,AttributeSetattrs,intdefStyleAttr){super(context,attrs,defStyleAttr);//获取属性typedArray=context.obtainStyledAttributes(attrs,R.styleable.Flowlayout);//maxLineanInt=typedArray.getInt(R.styleable.Flowlayout_InputNumberView_max,DEFAULT_LINE);//itemHorizontalMarginhorizontalMargin=typedArray.getDimension(R.styleable.FloeLayout_itemHorizontalMargin,DEFAULT_HORZONTAL_MARGIN);//itemVerticalMarginverticalMargin=typedArray.getDimension(R.styleable.FloeLayout_itemHorizontalMargin,DEFAULT_VERTIAL_MARGIN);//textMaxLinemMaxLine=typedArray.getInt(R.styleable.FloeLayout_maxLine,DEFAULT_TEXT_MAX_LENGTH);//textColortextcolor=typedArray.getColor(R.styleable.Flowlayout_textColor,getResources().getColor(R.color.black));//borderColortypedArray.getColor(R.styleable.Flowlayout_borderColor,getResources().getColor(R.color.black));//borderRadiusborderradius=typedArray.getInt(R.styleable.Flowlayout_borderRadius,DEFAULT_BORDER_RADIUS);typedArray.recycle();}publicTypedArraygetTypedArray(){returntypedArray;}publicvoidsetTypedArray(TypedArraytypedArray){this.typedArray=typedArray;}publicintgetAnInt(){returnanInt;}publicvoidsetAnInt(intanInt){this.anInt=anInt;}publicfloatgetHorizontalMargin(){returnhorizontalMargin;}publicvoidsetHorizontalMargin(floathorizontalMargin){this.horizontalMargin=horizontalMargin;}publicfloatgetVerticalMargin(){returnverticalMargin;}publicvoidsetVerticalMargin(floatverticalMargin){this.verticalMargin=verticalMargin;}publicintgetmMaxLine(){returnmMaxLine;}publicvoidsetmMaxLine(intmMaxLine){this.mMaxLine=mMaxLine;}publicintgetTextcolor(){returntextcolor;}publicvoidsetTextcolor(inttextcolor){this.textcolor=textcolor;}publicintgetBorderradius(){returnborderradius;}publicvoidsetBorderradius(intborderradius){this.borderradius=borderradius;}@OverrideprotectedvoidonLayout(booleanchanged,intl,intt,intr,intb){}}

把子view添加进来

有两种方法,第一种是直接在xml布局中进行添加,第二种就是想listview一样使用适配器来进行添加

我们使用第二种

publicvoidsettextList(List<String>data){this.mList.clear();this.mList.addAll(data);setUpText();}privatevoidsetUpText(){//先清空原来的内容removeAllViews();//添加子view进来for(Strings:mList){TextViewtextView=newTextView(getContext());textView.setText(s);//设置相关属性addView(textView);}}

在主活动中进行添加

publicclassTrueActiivtyextendsAppCompatActivity{privateList<String>data;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_true_actiivty);FlowLayoutflowLayout=findViewById(R.id.flow_layout);data=newArrayList<>();data.add("键盘");data.add("显示器");data.add("鼠标");data.add("iPad");data.add("air pot");data.add("女装");data.add("男鞋");data.add("男装");flowLayout.settextList(data);}}

六、自定义view绘制几何图形

1.直接在java文件中进行操作

importandroidx.appcompat.app.AppCompatActivity;importandroid.content.Context;importandroid.graphics.Canvas;importandroid.graphics.Color;importandroid.graphics.Paint;importandroid.graphics.Path;importandroid.os.Bundle;importandroid.view.View;publicclassMainActivityextendsAppCompatActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(newTestView(this));}privateclassTestViewextendsView{publicTestView(Contextcontext){super(context);}@OverrideprotectedvoidonDraw(Canvascanvas){super.onDraw(canvas);//设置一个背景图片canvas.drawColor(Color.YELLOW);//设置画笔Paintpaint=newPaint();paint.setStrokeWidth(30);paint.setStyle(Paint.Style.STROKE);//去掉锯齿paint.setAntiAlias(true);//绘制一个矩形canvas.drawRect(100,100,500,500,paint);//再绘制一个矩形paint.setStyle(Paint.Style.FILL);canvas.drawRect(600,100,1000,500,paint);//更改颜色paint.setColor(Color.BLUE);//画一个圆canvas.drawCircle(550,700,300,paint);//再画一个圆paint.setColor(Color.WHITE);canvas.drawCircle(510,720,100,paint);//画一个三角形paint.setColor(Color.RED);//定义一个路径Pathpath=newPath();path.moveTo(200,1000);path.lineTo(900,1000);path.lineTo(5500,1100);path.close();canvas.drawPath(path,paint);//绘制文字paint.setTextSize(100);paint.setColor(Color.BLUE);canvas.drawText("hello",300,1200,paint);}}}

定义一个内部类,继承自view,覆写onDraw()方法,利用画笔来绘制图形

2.运行效果:

七、MVC小实例及自定义view小实例

1.布局文件下添加控件

<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity2"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:id="@+id/text1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="输入位置:"/><EditTextandroid:id="@+id/editText1"android:layout_width="100dp"android:layout_height="wrap_content"android:hint="x坐标值:"/><EditTextandroid:id="@+id/editText2"android:layout_width="100dp"android:layout_height="wrap_content"android:hint="y坐标值:"/><Buttonandroid:id="@+id/button1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="确定"/></LinearLayout><com.example.customviewactivity.TestViewandroid:id="@+id/testView"android:layout_width="match_parent"android:layout_height="match_parent"></com.example.customviewactivity.TestView></LinearLayout>

2.设置一个类继承自view

packagecom.example.customviewactivity;importandroid.content.Context;importandroid.graphics.Canvas;importandroid.graphics.Color;importandroid.graphics.Paint;importandroid.util.AttributeSet;importandroid.view.View;importandroidx.annotation.Nullable;publicclassTestViewextendsView{intx,y;publicTestView(Contextcontext,@NullableAttributeSetattrs){super(context,attrs);}protectedvoidsetXY(int_x,int_y){x=_x;y=_y;}@OverrideprotectedvoidonDraw(Canvascanvas){super.onDraw(canvas);canvas.drawColor(Color.CYAN);Paintpaint=newPaint();paint.setAntiAlias(true);paint.setColor(Color.BLACK);canvas.drawCircle(x,y,40,paint);paint.setColor(Color.WHITE);canvas.drawCircle(x-8,y-8,8,paint);}}

重写onDraw()方法,进行绘制

3.主活动java文件下编辑代码

packagecom.example.customviewactivity;importandroidx.appcompat.app.AppCompatActivity;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.Button;importandroid.widget.EditText;publicclassMainActivity2extendsAppCompatActivityimplementsView.OnClickListener{EditTextedit_x,edit_y;Buttonbtn;TestViewtestView;intx1=150,y1=50;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);edit_x=findViewById(R.id.editText1);edit_y=findViewById(R.id.editText2);btn=findViewById(R.id.button1);testView=findViewById(R.id.testView);testView.setXY(x1,y1);btn.setOnClickListener(this);}@OverridepublicvoidonClick(Viewv){x1=Integer.parseInt(edit_x.getText().toString());y1=Integer.parseInt(edit_y.getText().toString());testView.setXY(x1,y1);//每次给到一个新的xy值,必须进行刷新testView.invalidate();}}

4.运行效果

实现效果:小球跟随输入的坐标位置移动

5.MVC思想:

主活动的xml文件就是 VIEW 层

主活动java文件 就是 Contral 层

TestView 就是 Model



作者:刂彐
链接:https://www.jianshu.com/p/8b7ea3a45f77
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值