一、view的測量
EXACTLY :精確值模式,當把空間的layout_width屬性或者layout_height的屬性設置為具體的數值時,或者指定為match_parent時候,系統就是使用的EXACTLY 模式;
AT_MOST: 最大值模式,當空間的layout_width屬性或者layout_height屬性指定為wrap_content時候,控件大小跟著控件的內容變化而變化,此時控件的尺寸只要不超過父控件允許的最大尺寸即可。
UNSPECIFIED: 這個屬性比較奇怪,不指定其測量大小模式,view想多大就多大,通常情況下只有在繪制自定義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;}}
<?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>
<?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之后再重寫onDraw方法,并在Canvas對象上來繪制需要的圖形
以繪制一個閃光的文字作為例子
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>
<?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
<?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>
左邊
<?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>
左邊
<?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>
左邊
<?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>
<?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>
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);}}
里邊代碼很詳盡,包含了暴露接口、處理事件的過程
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);}}
<?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
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();}
<?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>
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){}}
在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);}}
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()方法,利用畫筆來繪制圖形
<?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>
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()方法,進行繪制
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();}}
實現效果:小球跟隨輸入的坐標位置移動
主活動的xml文件就是 VIEW 層
主活動java文件 就是 Contral 層
TestView 就是 Model