Android开发之自定义View(一)

简介: Android常见的自定义控件有三种方式:继承View继承原有的控件,在原有控件的基础上进行修改重新拼装组合今天先来简单说一说第一种也是最复杂的一种~~ 剩下的下次再说~~继承View,重写onDraw方法,但是注意采用这种方式需要自己在代码中来支持熟悉的wrap_content、padding属性。
Android常见的自定义控件有三种方式:
  • 继承View
  • 继承原有的控件,在原有控件的基础上进行修改
  • 重新拼装组合

今天先来简单说一说第一种也是最复杂的一种~~ 剩下的下次再说~~

继承View,重写onDraw方法,但是注意采用这种方式需要自己在代码中来支持熟悉的wrap_content、padding属性。

1、想好需要自定义的属性,在values下创建一个attrs.xml,这里我就演示一个简单的颜色,自定义一个属性集合,命名为CustomView,有一个格式为color的属性custom_color

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomView">
        <attr name="custom_color" format="color"></attr>
    </declare-styleable>
</resources>

2、自定义View

public class CustomView extends View {

    private Paint mPaint = new Paint();// 创建一个画笔;
    private int mColor = Color.RED; //默认为红色

    public CustomView(Context context) {
        super(context);
    }

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        //加载自定义属性集合CustomView
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
        //解析CustomView中自定义的属性custom_color,id为R.styleable.CustomView_custom_color,如果没有就默认为红色
        mColor = a.getColor(R.styleable.CustomView_custom_color, Color.RED);
        //释放资源,方便下次使用
        a.recycle();

        //初始化画笔的参数
        mPaint.setColor(mColor);// 设置画笔颜色
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(100, 100, 50, mPaint);// 用画笔在画布上添加一个圆
    }
}

3、布局中使用,注意这里使用的时候一定要用全类名,要想用自定义属性,必须在布局中加入如下代码,这样自定义属性就可以用app打头:

xmlns:app="http://schemas.android.com/apk/res-auto"

设置宽高为match_parent,并设置了背景色和自定颜色

<com.example.administrator.diyview.CustomView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#123456"
        app:custom_color="#000000" />

4、运行效果图

img_f3c579fda863abaf9a4bfe2060b448fd.png
自定义View1.png

显示的是一个青色的背景和一个黑色的圆

5、注意:
这种方式无论怎么设置padding的值或者更改宽和高为wrap_content,执行效果都如上,原因就如开头所说,需要自己处理,那么如何处理呢?

(1) 处理padding
在android:layout_width 和 android:layout_height 都为 match_parent 时,我们考虑一下左边和上边的padding

<com.example.administrator.diyview.CustomView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#123456"
        android:paddingLeft="100dp"
        android:paddingTop="100dp"
        app:custom_color="#000000" />

在onDraw()方法中设置padding

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int paddingLeft = getPaddingLeft();
        int paddingTop = getPaddingTop();
        canvas.drawCircle(paddingLeft + 100, paddingTop + 100, 50, mPaint);
    }

运行效果:

img_05a091a1205118f77bf4acfec09d938b.png
自定义View2.png

(2)处理wrap_content
为什么要单独处理wrap_content呢?这和View的工作原理有关,View经过measure、layout和draw显示出来,其中measure时需要用到MeasureSpec的变量(包含SpecMode和SpecSize),其中SpecSize指定了特定测试模式下的大小,SpecMode指定了测量的模式,分为三类:

  • UNSPECIFIED
    父容器对View无任何限制,一般用于系统内部
  • EXACTLY
    View的最终大小就是SpecSize指定的值,适用于指定具体大小和match_parent的形式
  • AT_MOST
    父容器指定了一个SpecSize,View不能超过它,适用于wrap_content

当使用wrap_content时,SpecSize其实就是父容器中可用空间的大小,即View的宽和高等于父容器当前剩余的当前剩余空间大小,和使用match_parent一样,那么怎么处理?也很简单,只要重写onMeasure方法,在AT_MOST模式时,设置一个具体的宽高即可:

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取宽和高的SpecMode和SpecSize
        int wSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int wSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int hSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int hSpecSize = MeasureSpec.getSize(heightMeasureSpec);

        //分别判断宽高是否设置为wrap_content
        if (wSpecMode == MeasureSpec.AT_MOST && hSpecMode == MeasureSpec.AT_MOST) {
            //宽高都为wrap_content,直接指定为400
            setMeasuredDimension(400, 400);

        } else if (wSpecMode == MeasureSpec.AT_MOST) {
            //只有宽为wrap_content,宽直接指定为400,高为获取的SpecSize
            setMeasuredDimension(400, hSpecSize);

        } else if (hSpecMode == MeasureSpec.AT_MOST) {
            //只有高为wrap_content,高直接指定为400,宽为获取的SpecSize
            setMeasuredDimension(wSpecSize, 400);

        }
    }

此时布局如下:

<com.example.administrator.diyview.CustomView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#123456"
        android:paddingLeft="50dp"
        android:paddingTop="50dp"
        app:custom_color="#000000" />

运行效果:

img_f9949798875aedd93d6955430534f66f.png
自定义View3.png
目录
相关文章
|
1月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
239 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
1月前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
206 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
1月前
|
移动开发 Rust JavaScript
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
524 4
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
2月前
|
开发工具 Android开发
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
489 11
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
|
1月前
|
移动开发 Android开发
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
122 0
|
2月前
|
Java 开发工具 Maven
【01】完整的安卓二次商业实战-详细的初级步骤同步项目和gradle配置以及开发思路-优雅草伊凡
【01】完整的安卓二次商业实战-详细的初级步骤同步项目和gradle配置以及开发思路-优雅草伊凡
199 6
|
6月前
|
XML Java Android开发
Android自定义view之网易云推荐歌单界面
本文详细介绍了如何通过自定义View实现网易云音乐推荐歌单界面的效果。首先,作者自定义了一个圆角图片控件`MellowImageView`,用于绘制圆角矩形图片。接着,通过将布局放入`HorizontalScrollView`中,实现了左右滑动功能,并使用`ViewFlipper`添加图片切换动画效果。文章提供了完整的代码示例,包括XML布局、动画文件和Java代码,最终展示了实现效果。此教程适合想了解自定义View和动画效果的开发者。
322 65
Android自定义view之网易云推荐歌单界面
|
4月前
|
安全 数据库 Android开发
在Android开发中实现两个Intent跳转及数据交换的方法
总结上述内容,在Android开发中,Intent不仅是活动跳转的桥梁,也是两个活动之间进行数据交换的媒介。运用Intent传递数据时需注意数据类型、传输大小限制以及安全性问题的处理,以确保应用的健壯性和安全性。
357 11
|
4月前
|
移动开发 Java 编译器
Kotlin与Jetpack Compose:Android开发生态的演进与架构思考
本文从资深Android工程师视角深入分析Kotlin与Jetpack Compose在Android系统中的技术定位。Kotlin通过空安全、协程等特性解决了Java在移动开发中的痛点,成为Android官方首选语言。Jetpack Compose则引入声明式UI范式,通过重组机制实现高效UI更新。两者结合不仅提升开发效率,更为跨平台战略和现代架构模式提供技术基础,代表了Android开发生态的根本性演进。
181 0
|
5月前
|
安全 Java Android开发
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
267 0
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡

热门文章

最新文章

下一篇
oss云网关配置