进阶之自定义View之组合控件

打造高级Android自定义组合View 自定义View是指开发者根据特定需求,在Android框架提供的基础View之上,通过继承现有的View类或实现View接口,来自定义的组件。这种做法在Android应用开发中非常重要,因为它可以提高用户界面的灵活性和应用的个性化程度。通过自定义View,开发者可以创建完全符合应用风格的UI组件,避免了重复造轮子的工作,并且有助于保持项目代码的整洁与模块化。增强用户交互体验:自定义View可以实现丰富的交互效果和流畅的动画效果,提升用户体验。 阅读详情

对于Android小伙伴来说,自定义View是一个初级程序员进阶中高级程序员所必需掌控的技能。
话不多说,接下来我们直接开始讲解:
自定义View按类型来划分的话,自定义View的实现方式大概可以分为三种:

  1. 组合控件
  2. 继承控件
  3. 自绘控件

今天这一篇我们讲解的就是组合控件。

  1. 定义标题栏布局文件 activity_common_title.xml。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns: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="50dp"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/ivBack"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginLeft="10dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:src="@drawable/ic_reply_black_24dp"/>

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:textSize="22dp"
        android:textStyle="bold"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
  1. 抽取一个公共的BaseView
public class BaseView extends RelativeLayout {
    protected Context mContext;
    protected LayoutInflater mInflater;

    public BaseView(Context context) {
        this(context, null);
    }

    public BaseView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BaseView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }


    private void initView(Context context) {
        mContext = context;
        mInflater = LayoutInflater.from(mContext);
        int resourceId = getResourceId();
        if (resourceId > 0) {
            View view = inflate(mContext, resourceId, this);
            initView(view);
        }
    }

    /**
     * 获取布局文件
     *
     * @return
     */
    protected int getResourceId() {
        return 0;
    }

    /**
     * 初始化布局
     *
     * @param view
     */
    protected void initView(View view) {

    }

    public void destroyView() {
        unbindDrawables(this);
    }

    /**
     * @param view
     */
    private void unbindDrawables(View view) {
        if (null == view) {
            return;
        }
        if (view.getBackground() != null) {
            Drawable drawable = view.getBackground();
            if (null != drawable) {
                drawable.setCallback(null);
                drawable = null;
            }

        }
        if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
                unbindDrawables(((ViewGroup) view).getChildAt(i));
            }
            ((ViewGroup) view).removeAllViews();
        } else if (view instanceof ImageView) {
            Drawable drawable = ((ImageView) view).getDrawable();
            if (null != drawable) {
                drawable.setCallback(null);
                drawable = null;
            }
        }
        view = null;
    }
}
  1. 根据给定布局实现自定义View
public class CommonTitleView extends BaseView {
    private ImageView mIvBack;//返回按钮
    private TextView mTvTitle;//标题
    private View.OnClickListener mLeftOnClickListener;

    public void setLeftOnClickListener(OnClickListener mLeftOnClickListener) {
        this.mLeftOnClickListener = mLeftOnClickListener;
    }

    public CommonTitleView(Context context) {
        this(context,null);
    }

    public CommonTitleView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

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

    @Override
    protected int getResourceId() {
        return R.layout.view_common_title;
    }

    @Override
    protected void initView(View view) {
        mIvBack = view.findViewById(R.id.ivBack);
        mTvTitle = view.findViewById(R.id.tvTitle);
        mIvBack.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mLeftOnClickListener.onClick(v);
            }
        });
    }

    // 设置标题
    public void setTitle(String title){
        mTvTitle.setText(title);
    }

    @Override
    public void destroyView() {
        super.destroyView();
    }
}
  1. 在Activity的布局文件中添加CommonTitleView
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns: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">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.hyq.customviewdome.view.CommonTitleView
        android:id="@+id/cTview"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        tools:ignore="MissingConstraints" />

</androidx.constraintlayout.widget.ConstraintLayout>
  1. 在Activity中操作CommonTitleView
class MainActivity : AppCompatActivity() {
    private lateinit var cTview: CommonTitleView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        cTview = findViewById(R.id.cTview)

        cTview.setTitle("自定义View")
        cTview.setLeftOnClickListener { finish() }

    }
}

效果图
在这里插入图片描述

android自定义view之组合控件、重写控件 立即下载

相关推荐

自定义View—RadioGroup(kotlin版)

借助LinerLayout实现RadioGroup效果,kotlin编码,菜单图标使用Iconfont

安卓开发:自定义组合控件布局(kotlin语言)

/ 4. 处理事件。

m0_62545462的博客 779

Android自定义View之组合控件 ---- LED数字时钟

Android自定义View之组合控件 ---- LED数字时钟

Kotlin的自定义控件、Adapter

引入布局的技巧解决了重复编写布局的问题,但如果遇到响应事件的情况时,仍然需要在每个Activity中重复编写这些响应事件。而这种情况我们最好使用自定义控件来解决。因为是使用系统现成的控件进行编写,在最开始是我们编写的自定义控件,需要继承系统的控件。//TitleLayout的主构造函数,在布局中引入该控件时就会调用这个方法//init的初始化代码块,在创建类实例对象时执行init {现在自定义控件已经创建好了,让我们在布局文件中引用它,修改init {//返回按钮的点击事件。

qq_44016573的博客 2209

Android 使用Kotlin自定义View的方法教程

最近想加强一下自定义view方面的学习,正好也在学习Kotlin,所以就尝试着用Kotlin写一下简单的自定义view,下面这篇文章主要给大家介绍了关于Android使用Kotlin自定义View的方法教程,需要的朋友可以参考下。

Kotlin自定义菜单控件

主要为大家详细介绍了Kotlin自定义菜单控件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

Android的View体系与自定义View系列一:(Kotlin版)

关于Android的View你需要知道的基础知识

weixin_44755408的博客 2928

无人机频谱侦测与智能识别技术实战解析

本文深入解析无人机频谱侦测与智能识别技术实战应用,涵盖无线电侦测、信号处理和定位技术等核心内容。通过频谱分析、特征提取和机器学习算法优化,实现高精度无人机识别与定位,并分享复杂环境下的应对策略和系统集成经验。

weixin_28419039的博客 489

自定义控件的小总结------1组合式控件

自定义控件,总的来说有3种方式,自绘控件,继承控件,组合式控件 自绘控件 主要是使用Paint画笔和Cavas画布,进行绘制; 继承控件 主要是继承某一父类,然后在此基础上,定义自己想要的效果和功能;比如垂直的进度条,可以继承普通的ProgressBar然后进行方向的旋转设置,原本进度条的方法依然可以继续使用。 其实所有的控件都继承自view类,严格来说这种方式使用最多。 组合式控件 ...

jakezhang1990的专栏 436

手把手教你配置SAP PP供应区域(Supply Area):实现线边仓精准发料与物料流优化

本文详细解析了SAP PP供应区域(Supply Area)的配置方法,帮助企业实现线边仓精准发料与物料流优化。通过三级优先级逻辑和四步配置法,系统可自动识别最优组件来源位置,显著提升生产订单处理效率和库存准确率。文章还提供了典型问题解决方案和性能优化技巧,适用于离散制造和重复制造场景。

weixin_29275257的博客 434

已解决-Parallels Desktop 16 网络初始化失败:您的虚拟机将继续正常运作,但将无法连接网络

我是月球挖掘机,相信不少打工人为了尝鲜已经更新了MacOS 11 Big Sur,当然,苹果每次的系统大更新,都会给我们软件的功能无法使用惊喜,这次的也不例外。 这个问题是我在更新macOS Big Sur之后,Parallels Desktop打开虚拟机后,提示: 报错信息 网络初始化失败:您的虚拟机将继续正常运作,但将无法连接网络 这是我的软件版本: 起初我以为是我的虚拟机坏了,结果重装了一遍虚拟机,没有任何用处。我开始在网上找方法,只能找到那个使用命令行打开软件的命令,除此之外没有了

月球挖掘机 5万+

kotlin自定义view

思路: 自定义的view类继承于view类,在xml中赋予它布局属性,在MainActivity中调用xml定义的自己写的view;使用ValueAnimator改变onDraw中绘画的控件的属性,当属性的值改变时,会触发invalidate()函数,系统自己去调用onDraw方法,就形成了动画。 代码: 自定义view的类: class animator_View : View { constructor(context: Context,attributeSet: Attribut

chuyouyinghe的专栏 3146

Arduino-CRSF库详解:嵌入式端CRSF协议解析与ELRS接收机集成

CRSF(Crossfire Serial Protocol)是一种面向FPV无人机的轻量级、高实时性串行通信协议,采用单总线异步传输与8位CRC-8校验机制,广泛应用于遥控链路与遥测交互。其核心在于帧同步(0xC8起始字节)、反相逻辑电平及无重传的广播式设计,对嵌入式平台的UART精度、电平匹配和状态机健壮性提出严苛要求。Arduino-CRSF库正是为资源受限MCU(如ESP32、STM32、ATmega328P)提供零配置、中断安全的协议解析能力,封装了CRC查表计算、超时恢复、多级同步验证等关键机制

weixin_35756690的博客 416

一篇文章带你走近Android自定义view

系列文章目录 一篇文章带你走近Android自定义view 文章目录系列文章目录前言一、为什么要自定义view二、先看看一个超级简单的自定义view(三个构造函数)三、了解手机的坐标系四、使用Canvas画一个折线图(重写onDraw()方法)五、如何自定义属性,且在view中获取到属性的值(小提,在六中会有案例)六、绘制图案以及加入设置简单的动画(案例讲解很详细)七、自定义view的实现分类以及自定义组合控件的案例八、简单测量以及自定义接口实例来控制动画的更新计算表达式(onMeasure,TypeE

计蒙不吃鱼的博客 6026

影刀RPA:轻松搞定Excel表格自动化操作

影刀RPA是一款功能强大的自动化工具,通过模拟人类操作实现各种重复性任务的自动化。零代码操作:通过拖拽式流程设计器,无需编程基础即可快速上手。功能丰富:提供丰富的组件库,涵盖文件操作、数据处理等多种功能。高效稳定:支持多任务并行,确保任务的高效执行和稳定性。支持Python语法:内置数据表格,支持Python语法,对新手友好,同时具备循环功能。通过影刀RPA,您可以轻松实现Excel表格的拆分、列数据合并和归档工作的自动化。这不仅节省了手动操作的时间,还能确保数据处理的高效和准确,提升工作效率和管理水平。

watwrmoon的博客 2560

2023年全国职业院校技能大赛“信息安全管理与评估”-真题——赛题题目+答案解析

2023年全国职业院校技能大赛“信息安全管理与评估”-真题——赛题题目+答案解析

君逍遥o 6011

Android 自定义 View 进阶实战全解析:从扩展控件与组合控件入门,到 onMeasure 测量、onDraw 绘制、手势交互处理及自定义布局容器实现的完整开发指南

本文系统讲解了Android自定义View的开发方法与实践技巧。主要内容包括: 自定义View的三种实现方式:扩展控件(继承现有控件)、组合控件(整合多个控件)和完全自定义View(从零实现测量、绘制和交互)。 详细演示了扩展控件开发流程,以验证码倒计时按钮为例,展示如何基于TextView扩展功能,包括计时逻辑实现和状态管理。 介绍了组合控件的实现方法,通过可折叠文本控件案例说明如何组合现有控件并支持XML属性配置。 深入讲解了完全自定义View的核心技术: onMeasure测量流程 onDraw图形绘

OuO-1 的博客 1501

SAP S/4HANA 数据归档的实施方法

实施 SAP S/4HANA 数据归档是一个系统的过程,涉及到策略的定义、技术的执行以及后续的维护和验证。正确的归档策略不仅能优化系统性能,还能帮助企业降低运营成本,确保数据安全,并符合相关法律法规的要求。通过以上案例,我们可以看到不同行业如何依据自己的业务需求和法规要求,利用 SAP S/4HANA 的强大功能来实现数据归档的目标。这些实践证明了数据归档在现代企业信息管理中的重要地位和作用。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 890

自定义View的尝试-A到Z快速搜索sideBar

开始之前先来一段我觉得写得很好的话,相信自己才能在开发之路越走越远 很多大神都说自定义View是进阶的必经之路,那么走起吧

lan_学习分享 1441

vscode中运行gcc -v命令失败了,提示:gcc不是内部或外部命令...如何解决?

🏆本文收录于 《全栈Bug调优(实战版)》 专栏,该专栏专注于分享我在真实项目开发中遇到的各类疑难Bug及其深层成因,并系统提供高效、可复现的解决思路和实操方案。无论你是刚入行的新手开发者,还是拥有多年项目经验的资深工程师,本专栏都将为你提供一条系统化、高质量的问题排查与优化路径,助力你加速成长,攻克技术壁垒,迈向技术价值最大化与职业发展的更高峰🚀!

**My Coding Family** 976

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Android进阶 :实现自定义View

有时候我们会想要实现一些复杂或者是独特的组件效果,这时候系统提供的组件可能不能满足我们的需求,这个时候我们一般就会有两个解决办法,**一是上网查找开源的控件库**,一些流行的开源库可以满足我们的绝大部分需求。不过这些开源库也具有时效性,因为它们的更新得不到保证。二就是我们自己实现我们需要的控件,开源库本质也是自定义View。 不过实现自定义View需要我们对View的事件分发以及View的工作流程有一定了解,可以查看之前的博客: 1. [Android进阶 View事件体系(一):概要介绍和实现View的

Tai_Monster的博客 1487

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

android UI进阶之自定义组合控件

好久没写博客了。实在是忙不过来,不过再不总结总结真的不行了。慢慢来吧,有好多需要去总结的,博客里还是记录ui方面的。 今天和大家分享下组合控件的使用。很多时候android自定义控件并不能满足需求,如何做呢?很多方法,可以自己绘制一个,可以通过继承基础控件来重写某些环节,当

notice501的专栏 2万+

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

[进阶] UI - Android 自定义View

为什么需要自定义View 现有的View满足不了你的需求,也没有办法从已有控件派生一个出来;界面元素需要自己绘制。 现有View可以满足要求,把它做成自定义View只是为了抽象 为这个自定义View提供若干方法,方便调用着操纵View。 通常做法是派生一个已有View,或者结合xml文件直接inflate。 Attention 能够用Android基础控件解决的问题就尽量用基础控...

vivian的专栏 295

android UI进阶之自定义组合控件之一

很多时候android自定义控件并不能满足需求,如何做呢?很多方法,可以自己绘制一个,可以通过继承基础控件来重写某些环节,当然也可以将控件组合成一个新控件,这也是最方便的一个方法。今天就来介绍下如何使用组合控件,将通过一个实例来介绍。 实现一个带图片和文字的按钮,如图所示: 整个过程可以分四步走。第一步,定义一个layout,实现按钮内部的布局。代码如下: <LinearLay

sada09的专栏 956

Android零基础入门第24节:自定义View简单使用

当我们开发中遇到Android原生的组件无法满足需求时,这时候就应该自定义View来满足这些特殊的组件需求。

鑫鱻的博客 2020

Android进阶:自定义View实战

自定义View主要分为两种:继承现有控件和完全自定义。继承现有控件可以在原有控件的基础上进行扩展和修改,而完全自定义则从零开始构建控件。完全自定义控件需要重写View的onDraw方法,使用Canvas类进行绘图。 init(); @Override 自定义属性可以让我们更灵活地控制控件的样式和行为。通过在中定义属性,并在自定义View中读取这些属性,可以实现这一功能。在。

2501_92488972的博客 321
上一篇: SharedPreference.Editor的apply和commit方法异同
下一篇: 进阶之自定义View之继承控件
jhonjson
博客等级 码龄11年 220粉丝 195原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值