需要代码和图片集或者运行有问题请点赞关注收藏后评论区留言~~~
一、视图的绘制方法
测量完控件的宽高,接下来就要 绘制控件图案了,此时可以重写两个视图绘制方法,分别是onDraw和dispatchDraw,它们的区别主要有以下两点
1:onDraw既可用于普通控件,也可用于布局类视图,而dispatchDraw专门用于布局类视图,像线性布局LinearLayout,相对布局RelativeLayout都属于布局类视图
2:onDraw方法先执行,dispatchDraw方法后执行,这两个方法中间再执行下级视图的绘制方法
它们绘制方法的执行顺序如下图
不管是onDraw方法还是dispatchDraw方法,它们的入参都是Canvas画布对象,在画布上绘图相当于在屏幕上绘图,绘图本身是个很大的课题,画布的用法也多种多样,Canvas提供了下列三种方法
1:划定可绘制的区域
2:在区域内部绘制图形
3:画布的控制操作
接下来演示如何通过画布和画笔描绘不同的几何图形,以绘制圆角矩形与其他图形为例
初始化为不画图 但是点击下拉框可以选择图形
选择矩形如下
选择圆形如下
选择画叉叉如下
代码如下
Java类
package com.example.chapter10; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.Spinner; import androidx.appcompat.app.AppCompatActivity; import com.example.chapter10.widget.DrawRelativeLayout; public class ShowDrawActivity extends AppCompatActivity { private DrawRelativeLayout drl_content; // 声明一个绘画布局对象 private Button btn_center; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_show_draw); // 从布局文件中获取名叫drl_content的绘画布局 drl_content = findViewById(R.id.drl_content); btn_center = findViewById(R.id.btn_center); initTypeSpinner(); // 初始化绘图方式的下拉框 } // 初始化绘图方式的下拉框 private void initTypeSpinner() { ArrayAdapter<String> drawAdapter = new ArrayAdapter<String>(this, R.layout.item_select, descArray); Spinner sp_draw = findViewById(R.id.sp_draw); sp_draw.setPrompt("请选择绘图方式"); sp_draw.setAdapter(drawAdapter); sp_draw.setOnItemSelectedListener(new DrawSelectedListener()); sp_draw.setSelection(0); } private String[] descArray = {"不画图", "画矩形", "画圆角矩形", "画圆圈", "画椭圆", "onDraw画叉叉", "dispatchDraw画叉叉"}; private int[] typeArray = {0, 1, 2, 3, 4, 5, 6}; class DrawSelectedListener implements OnItemSelectedListener { public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { int type = typeArray[arg2]; if (type == 5 || type == 6) { btn_center.setVisibility(View.VISIBLE); } else { btn_center.setVisibility(View.GONE); } drl_content.setDrawType(type); // 设置绘图布局的绘制类型 } public void onNothingSelected(AdapterView<?> arg0) {} } }
按钮类如下
package com.example.chapter10.widget; import android.annotation.SuppressLint; import android.content.Context; import android.os.Build; import android.util.AttributeSet; import android.util.Log; import android.widget.Button; import com.example.chapter10.R; @SuppressLint("AppCompatCustomView") public class CustomButton extends Button { private final static String TAG = "CustomButton"; public CustomButton(Context context) { super(context); Log.d(TAG, "只有一个输入参数"); } public CustomButton(Context context, AttributeSet attrs) { this(context, attrs, R.attr.customButtonStyle); Log.d(TAG, "有两个输入参数"); } public CustomButton(Context context, AttributeSet attrs, int defStyleAttr) { // 使defStyleAttr奏效的三个条件: // 1、attrs.xml增加定义风格属性(如customButtonStyle),且format值为reference // 2、styles.xml增加某种风格的样式定义(如CommonButton) // 3、AndroidManifest.xml的application节点的android:theme指定了哪个主题(如AppTheme),就在该主题内部补充风格属性与样式的对应关系,如 // <item name="customButtonStyle">@style/CommonButton</item> //super(context, attrs, defStyleAttr); // 设置默认的样式属性 // 下面不使用defStyleAttr,直接使用R.style.CommonButton定义的样式 this(context, attrs, 0, R.style.CommonButton); Log.d(TAG, "有三个输入参数"); } @SuppressLint("NewApi") public CustomButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); Log.d(TAG, "有四个输入参数"); } }
下拉框如下
package com.example.chapter10.widget; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import androidx.viewpager.widget.PagerTabStrip; import com.example.chapter10.R; import com.example.chapter10.util.Utils; public class CustomPagerTab extends PagerTabStrip { private final static String TAG = "CustomPagerTab"; private int textColor = Color.BLACK; // 文本颜色 private int textSize = 15; // 文本大小 public CustomPagerTab(Context context) { super(context); } public CustomPagerTab(Context context, AttributeSet attrs) { super(context, attrs); if (attrs != null) { // 根据CustomPagerTab的属性定义,从XML文件中获取属性数组描述 TypedArray attrArray = context.obtainStyledAttributes(attrs, R.styleable.CustomPagerTab); // 根据属性描述定义,获取XML文件中的文本颜色 textColor = attrArray.getColor(R.styleable.CustomPagerTab_textColor, textColor); // 根据属性描述定义,获取XML文件中的文本大小 // getDimension得到的是px值,需要转换为sp值 textSize = Utils.px2sp(context, attrArray.getDimension( R.styleable.CustomPagerTab_textSize, textSize)); Log.d(TAG, "origin textSize="+attrArray.getDimension( R.styleable.CustomPagerTab_textSize, textSize)); Log.d(TAG, "textColor=" + textColor + ", textSize=" + textSize); attrArray.recycle(); // 回收属性数组描述 } } // //PagerTabStrip没有三个参数的构造方法 // public CustomPagerTab(Context context, AttributeSet attrs, int defStyleAttr) { // } @Override protected void onDraw(Canvas canvas) { // 绘制方法 super.onDraw(canvas); setTextColor(textColor); // 设置标题文字的文本颜色 setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize); // 设置标题文字的文本大小 } }
XML文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="5dp" > <RelativeLayout android:layout_width="match_parent" android:layout_height="40dp" > <TextView android:id="@+id/tv_draw" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:gravity="center" android:text="绘图方式:" android:textColor="@color/black" android:textSize="17sp" /> <Spinner android:id="@+id/sp_draw" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_toRightOf="@+id/tv_draw" android:gravity="left|center" android:spinnerMode="dialog" /> </RelativeLayout> <!-- 自定义的绘画视图,需要使用全路径 --> <com.example.chapter10.widget.DrawRelativeLayout android:id="@+id/drl_content" android:layout_width="match_parent" android:layout_height="150dp" > <Button android:id="@+id/btn_center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="10dp" android:layout_centerInParent="true" android:text="我在中间" android:textColor="@color/black" android:textSize="20sp" android:visibility="gone" /> </com.example.chapter10.widget.DrawRelativeLayout> </LinearLayout>
创作不易 觉得有帮助请点赞关注收藏~~~