Android开发自定义View
<p> Android中View组件的作用类似于Swing变成中的JPanel,它只是一个空白的矩形区域,View组件中没有任何内容。对于Android应用的其他UI组件来说,它们都继承了View组件,然后在View组件提供的空白区域绘制外观。</p><p> 当Android系统提供的UI组件不足以满足项目需求时,我们可以通过继承View并重写View类的一个或多个方法来自定义组件。</p>
<p> 通常可以被用户重写的方法如下:</p>
<p> 1.构造器:重写构造器是定制View的最基本的方式,当Java(或Kotlin)代码创建一个View实例或根据XML布局文件加载并构建界面时将调用该构造器。</p>
<p> 2.onFinishInflate():这是一个回调方法,当应用从XML布局文件加载该组件并利用它来构建界面之后,该方法将会被调用。</p>
<p> 3.onMeasure(int,int):调用该方法来检测View组件及其所包含的所有子组件的大小。</p>
<p> 4.onLayout(boolean,int,int,int,int):当该组件需要分配其子组件的位置、大小时,该方法就会被回调。</p>
<p> 5.onSizeChanged(int,int,int,int):当该组件的大小被改变时回调该方法。</p>
<p> 6.onDraw(Canvas):当该组件将要绘制它的内容时回调该方法。</p>
<p> 7.onKeyDown(int,KeyEvent):当按下某个键时触发该方法。</p>
<p> 8.onKeyUp(int,KeyEvent):当松开某个键时触发该方法。</p>
<p> 9.onTrackballEvent(MotionEvent):当发生轨迹球事件时触发该方法</p>
<p> 10.onTouchEvent(MotionEvent):当发生触摸屏事件时触发该方法</p>
<p> 11.onFocusChanged(boolean gainFocus,int direction,Rect previouslyFocusedRect):当该组件焦点发生改变时触发该方法。</p>
<p> 12.onWindowFocusChanged(boolean):当包含该组件的窗口失去或得到焦点时触发该方法。</p>
<p> 13.onAttachedToWindow():当把该组件放入某个窗口中时触发该方法</p>
<p> 14.onDetachedFromWindow():当把该组件从某个窗口中分离时触发该方法</p>
<p> 15.onWindowVisibilityChanged(int):当包含该组件的窗口的可见性发生改变时触发该方法。</p>
<p> 当我们在开发自定义View时,通常仅需根据业务需求重写上面的部分方法,如果自定义组件仅仅只是组合现有的组件那就更加简单了,仅仅实现自定义组件的构造器然后使用LayoutInflater加载布局文件即可。</p>
<p> ⒈实例自定义View</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> cn.coreqi.view;
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span>
<span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.content.Context;
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.graphics.Canvas;
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.graphics.Color;
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.graphics.Paint;
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.util.AttributeSet;
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.view.MotionEvent;
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.view.View;
</span><span style="color: rgba(0, 128, 128, 1)">10</span>
<span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> DrawView <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> View {
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">float</span> currentX =<span style="color: rgba(0, 0, 0, 1)"> 40f;
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">float</span> currentY =<span style="color: rgba(0, 0, 0, 1)"> 50f;
</span><span style="color: rgba(0, 128, 128, 1)">14</span>
<span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">定义并创建画笔</span>
<span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 255, 1)">private</span> Paint p = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Paint();
</span><span style="color: rgba(0, 128, 128, 1)">17</span>
<span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> DrawView(Context context) {
</span><span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(context);
</span><span style="color: rgba(0, 128, 128, 1)">20</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">21</span>
<span style="color: rgba(0, 128, 128, 1)">22</span> <span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> DrawView(Context context, AttributeSet attrs) {
</span><span style="color: rgba(0, 128, 128, 1)">23</span> <span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(context, attrs);
</span><span style="color: rgba(0, 128, 128, 1)">24</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">25</span>
<span style="color: rgba(0, 128, 128, 1)">26</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当该组件将要绘制它的内容时触发该方法</span>
<span style="color: rgba(0, 128, 128, 1)">27</span> <span style="color: rgba(0, 0, 0, 1)"> @Override
</span><span style="color: rgba(0, 128, 128, 1)">28</span> <span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onDraw(Canvas canvas) {
</span><span style="color: rgba(0, 128, 128, 1)">29</span> <span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onDraw(canvas);
</span><span style="color: rgba(0, 128, 128, 1)">30</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置画笔的颜色</span>
<span style="color: rgba(0, 128, 128, 1)">31</span> <span style="color: rgba(0, 0, 0, 1)"> p.setColor(Color.RED);
</span><span style="color: rgba(0, 128, 128, 1)">32</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">绘制一个小圆(作为小球)</span>
<span style="color: rgba(0, 128, 128, 1)">33</span> <span style="color: rgba(0, 0, 0, 1)"> canvas.drawCircle(currentX,currentY,15F,p);
</span><span style="color: rgba(0, 128, 128, 1)">34</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">35</span>
<span style="color: rgba(0, 128, 128, 1)">36</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">为该组件的触碰事件重写事件处理方法</span>
<span style="color: rgba(0, 128, 128, 1)">37</span> <span style="color: rgba(0, 0, 0, 1)"> @Override
</span><span style="color: rgba(0, 128, 128, 1)">38</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> onTouchEvent(MotionEvent event) {
</span><span style="color: rgba(0, 128, 128, 1)">39</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">修改currentX,currentY两个成员变量</span>
<span style="color: rgba(0, 128, 128, 1)">40</span> currentX =<span style="color: rgba(0, 0, 0, 1)"> event.getX();
</span><span style="color: rgba(0, 128, 128, 1)">41</span> currentY =<span style="color: rgba(0, 0, 0, 1)"> event.getY();
</span><span style="color: rgba(0, 128, 128, 1)">42</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">通知当前组件重新绘制自己</span>
<span style="color: rgba(0, 128, 128, 1)">43</span> <span style="color: rgba(0, 0, 0, 1)"> invalidate();
</span><span style="color: rgba(0, 128, 128, 1)">44</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">返回true表明该处理方法已经处理该事件</span>
<span style="color: rgba(0, 128, 128, 1)">45</span> <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">46</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">47</span> }</pre>
</div>
<p>⒉在代码中创建自定义View</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> cn.coreqi;
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span>
<span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> androidx.appcompat.app.AppCompatActivity;
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span>
<span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.os.Bundle;
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.widget.LinearLayout;
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.coreqi.view.DrawView;
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span>
<span style="color: rgba(0, 128, 128, 1)"> 9</span>
<span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> MainActivity <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> AppCompatActivity {
</span><span style="color: rgba(0, 128, 128, 1)">11</span>
<span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)"> @Override
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onCreate(Bundle savedInstanceState) {
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate(savedInstanceState);
</span><span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">新建LinearLayout布局容器</span>
<span style="color: rgba(0, 128, 128, 1)">16</span> LinearLayout layout = <span style="color: rgba(0, 0, 255, 1)">new</span> LinearLayout(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置该Activity显示layout</span>
<span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(0, 0, 0, 1)"> setContentView(layout);
</span><span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建我们自定义的View组件</span>
<span style="color: rgba(0, 128, 128, 1)">20</span> DrawView draw = <span style="color: rgba(0, 0, 255, 1)">new</span> DrawView(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置自定义组件的最小宽度、高度</span>
<span style="color: rgba(0, 128, 128, 1)">22</span> draw.setMinimumWidth(300<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">23</span> draw.setMinimumHeight(500<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">24</span> <span style="color: rgba(0, 0, 0, 1)"> layout.addView(draw);
</span><span style="color: rgba(0, 128, 128, 1)">25</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">26</span> }</pre>
</div>
<p>⒊在XML布局文件中创建自定义View</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 255, 1)"><?</span><span style="color: rgba(255, 0, 255, 1)">xml version="1.0" encoding="utf-8"</span><span style="color: rgba(0, 0, 255, 1)">?></span>
<span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">androidx.constraintlayout.widget.ConstraintLayout </span><span style="color: rgba(255, 0, 0, 1)">xmlns:android</span><span style="color: rgba(0, 0, 255, 1)">="http://schemas.android.com/apk/res/android"</span>
<span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(255, 0, 0, 1)"> xmlns:app</span><span style="color: rgba(0, 0, 255, 1)">="http://schemas.android.com/apk/res-auto"</span>
<span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(255, 0, 0, 1)"> xmlns:tools</span><span style="color: rgba(0, 0, 255, 1)">="http://schemas.android.com/tools"</span>
<span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(255, 0, 0, 1)"> android:layout_width</span><span style="color: rgba(0, 0, 255, 1)">="match_parent"</span>
<span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(255, 0, 0, 1)"> android:layout_height</span><span style="color: rgba(0, 0, 255, 1)">="match_parent"</span>
<span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(255, 0, 0, 1)"> tools:context</span><span style="color: rgba(0, 0, 255, 1)">=".MainActivity"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 128, 128, 1)"> 8</span>
<span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">cn.coreqi.view.DrawView
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(255, 0, 0, 1)">android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/drawView"</span>
<span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(255, 0, 0, 1)"> android:layout_width</span><span style="color: rgba(0, 0, 255, 1)">="match_parent"</span>
<span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(255, 0, 0, 1)"> android:layout_height</span><span style="color: rgba(0, 0, 255, 1)">="match_parent"</span> <span style="color: rgba(0, 0, 255, 1)">/></span>
<span style="color: rgba(0, 128, 128, 1)">13</span>
<span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">androidx.constraintlayout.widget.ConstraintLayout</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<p> </p><br><br>
来源:https://www.cnblogs.com/fanqisoft/p/11017395.html
頁:
[1]