首页 > 其他分享 >《第三十一章 高级主题 - 自定义控件》

《第三十一章 高级主题 - 自定义控件》

时间:2024-09-02 20:24:32浏览次数:15  
标签:控件 自定义 int paint 第三十一章 context typedArray

一、引言

在 Android 开发中,为了满足特定的界面需求和交互效果,自定义控件是一项非常重要的技能。它能够让开发者根据具体的业务场景创建出独特且功能强大的用户界面元素。在本章中,我们将深入探讨自定义控件的两种主要方式:继承现有控件和完全自定义控件。

二、继承现有控件

(一)为什么要继承现有控件
现有控件通常提供了一些基本的功能和特性,但在某些情况下,可能无法完全满足我们的特定需求。通过继承现有控件,我们可以在其基础上进行扩展和修改,以实现更个性化的功能和外观。

(二)继承的步骤

  1. 选择要继承的控件:例如 TextViewButton 等。
  2. 创建子类:在新的类中继承所选的控件。

public class CustomTextView extends TextView {
    // 自定义的代码
}

(三)扩展功能

  1. 重写方法:可以重写控件的现有方法,如 onDrawonMeasure 等,以改变控件的绘制和测量行为。
  2. 添加新的属性:通过在 XML 布局文件中定义新的属性,并在代码中进行处理,来扩展控件的可配置性。

(四)示例:自定义具有特殊效果的 TextView

public class CustomTextView extends TextView {

    private int customColor;

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

    public CustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView);
        customColor = typedArray.getColor(R.styleable.CustomTextView_customColor, Color.BLACK);
        typedArray.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Paint paint = new Paint();
        paint.setColor(customColor);
        canvas.drawLine(0, 0, getWidth(), getHeight(), paint);
    }
}

在上述示例中,我们继承了 TextView 并添加了一个自定义颜色属性,然后在 onDraw 方法中绘制了一条直线。

三、完全自定义控件

(一)何时需要完全自定义控件
当现有的控件无法提供所需的基本架构和行为时,就需要进行完全自定义控件的开发。

(二)实现步骤

  1. 继承 View 或 ViewGroup 类:如果是单个控件,继承 View;如果是包含多个子控件的布局,继承 ViewGroup

public class CustomView extends View {
    // 自定义的代码
}

  1. 实现测量和绘制:重写 onMeasure 方法进行测量,onDraw 方法进行绘制。

  2. 处理触摸事件(可选):如果需要处理用户的触摸操作,重写相应的触摸事件方法。

(三)绘制过程

  1. 获取 Canvas 对象:在 onDraw 方法中通过参数获取。
  2. 使用绘图方法:如 drawRectdrawCircle 等绘制图形。
  3. 处理文字绘制:使用 Paint 对象设置文字样式和颜色。

(四)示例:完全自定义一个圆形按钮

public class CustomButton extends View {

    private int backgroundColor;
    private int textColor;
    private String text;

    public CustomButton(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomButton);
        backgroundColor = typedArray.getColor(R.styleable.CustomButton_backgroundColor, Color.RED);
        textColor = typedArray.getColor(R.styleable.CustomButton_textColor, Color.WHITE);
        text = typedArray.getString(R.styleable.CustomButton_text);
        typedArray.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int desiredWidth = 200;
        int desiredHeight = 200;

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int width;
        int height;

        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else if (widthMode == MeasureSpec.AT_MOST) {
            width = Math.min(desiredWidth, widthSize);
        } else {
            width = desiredWidth;
        }

        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else if (heightMode == MeasureSpec.AT_MOST) {
            height = Math.min(desiredHeight, heightSize);
        } else {
            height = desiredHeight;
        }

        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int radius = Math.min(getWidth(), getHeight()) / 2;

        Paint paint = new Paint();
        paint.setColor(backgroundColor);
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, paint);

        paint.setColor(textColor);
        paint.setTextSize(50);
        canvas.drawText(text, getWidth() / 2 - (paint.measureText(text) / 2), getHeight() / 2 + 25, paint);
    }
}

四、自定义控件的优化

(一)避免过度绘制
合理使用 Canvas 的裁剪区域和缓存机制,减少不必要的绘制操作。

(二)性能考量
在测量和绘制过程中,尽量减少计算量和对象创建,提高控件的响应性能。

(三)内存管理
注意控件中资源的释放,避免内存泄漏。

五、实际应用场景

(一)创建独特的用户界面元素
如具有特殊形状和交互效果的按钮、进度条等。

(二)实现复杂的布局
构建自定义的布局容器,实现更灵活的界面布局。

(三)适应特定的业务需求
根据具体的业务逻辑,定制具有特殊功能的控件。

六、总结

自定义控件是 Android 开发中的高级技能,通过继承现有控件和完全自定义控件,开发者能够实现更加丰富和独特的用户界面。在实际开发中,根据具体需求选择合适的自定义方式,并注重性能优化和用户体验,能够打造出高质量的 Android 应用。

希望通过本章的学习,您对 Android 自定义控件有了更深入的理解和掌握,能够在未来的开发工作中充分发挥创造力,为用户带来更加精彩的应用界面。

标签:控件,自定义,int,paint,第三十一章,context,typedArray
From: https://blog.csdn.net/weixin_47266126/article/details/141829326

相关文章

  • 自定义TOOLs(完全体Agent)
    1.Agents包括几个关键组件:-*Agent*:用于生成指令和执行动作的代理。-*Tool*:用于执行动作的函数。-*Memory*:用于存储历史对话和生成的指令。-*LLM*:用于生成指令和执行动作的LLM。2.例如:计算\搜索\知识库检索(多轮对话)fromlangchain.agentsimportload_to......
  • 收银系统源码-收银台ui自定义
    收银系统在很多门店日常经营中,使用率是非常高的。商品采购、出入库、商品销售、会员管理、线上商城订单核销等都离不开收银系统,很多门店的收银员是使用线下收银台时,想根据的操作习惯以及个人喜好调整收银台。1.调整收银台的整体ui收银台ui风格,收银员可以根据自己的个人喜好去自定......
  • 【Qt笔记】QTableView控件详解
     目录引言 一、定义与架构二、主要功能与特点2.1 显示表格数据2.2编辑表格数据2.3自定义外观和交互2.4数据排序和过滤2.5支持拖放操作2.6自适应大小2.7上下文菜单2.8信号与槽三、常用属性设置3.1设置模型3.2 设置选择模型3.3 隐藏垂直标题3.4 ......
  • 原生JS实现城市选择(输入提示)组控件
    先看效果图:功能需求:国内城市、国际城市切换首字母索引分类输入变化提示HTML代码<divclass="m-list"><divclass="g-sch"><ulclass="f-cbz-blankhide"><liclass="first"><pclass="u-......
  • 借助图形控件Aspose.PSD, 在 Java 中绘制几何形状
    最近,我们使用Aspose.PSDforJava实现了绘制诸如日食和线条等形状的功能。然而,这篇博文将更进一步,向您展示如何在Java中绘制几何形状。幸运的是,您可以使用这个Java绘图库以编程方式执行此操作,因为它是一个完整的包,可以在Java应用程序中处理形状。因此,没有额外的要求,我们可......
  • Sitecore 通过 processor 来自定义类似 github 的 not found 页面
    有一个需求是类似github的404页面,当访问不存在的页面时,需要满足以下几点:不是通过redirect或其他状态码让浏览器来跳转到到404页面;链接还是原来链接,但是页面内容是404;由于是MVC模式,功能由back-end来实现;状态码得是404。在基于sitecore的框架上,使用sitecore的p......
  • metershpere中如何调用自定义jar包中的方法
    背景:    在编写一些稍微复杂一点的逻辑的接口测试用例时,大家可以感觉到metershpere用起来并不方便,即使用已有的控件写出来了看起来也异常混乱,比如有多层循环逻辑再加上一些逻辑判断,场景变量,全局变量来回变更时,保证metershpere的界面会让你看的头晕。这时多数同学一定会......
  • 20240905_000339 mysql 存储过程 用户自定义变量
    自定义变量的特点一个@符号定义自定变量打印自定变量另一种定义方式查询赋值......
  • Prestashop安装问题:无法安装自定义模块
    Prestashop是一款免费开源的电子商务软件,它具有易于使用、功能丰富和高度可定制化等特点。如果在安装自定义模块时遇到问题,可能是由于以下原因:权限问题:确保你具有足够的权限来安装模块。你可以尝试以管理员身份运行安装程序。文件权限问题:确保自定义模块所在的文件夹及其子文件夹......
  • Scrapy:使用自定义列设置保存为 CSV 的指南
    在Scrapy中,你可以使用自定义列设置将数据保存为CSV文件。以下是一个基本的指南:定义你的数据项(Item):在你的Scrapy项目中,创建一个类来定义你要提取的数据项。每个数据项对应于CSV文件中的一列。处理数据:在你的爬虫(Spider)中,提取数据并将其存储在定义的数据项中。设置CSV输出:......