自定义控件

自定义控件——初识自定义控件 本文出自 “阿敏其人” 简书博客,转载或引用请注明出处。开发的时候,因为业务需求或者封装需要,我们会进行自定义控件。 说在前面,本篇涉及到一些东西 * onMeasure * onLayout * onDraw * MeasureSpec (32位二进制数,头两位模式(Mode),后两位大小(Size)) * onFinishInflate * ViewGr 阅读详情
cnblogs.com

[Android自定义控件] Android自定义控件


Android系统的视图结构的设计也采用了组合模式,即View作为所有图形的基类,Viewgroup对View继承扩展为视图容器类。

View定义了绘图的基本操作

基本操作由三个函数完成:measure()、layout()、draw(),其内部又分别包含了onMeasure()、onLayout()、onDraw()三个子方法。具体操作如下:

1、measure操作

     measure操作主要用于计算视图的大小,即视图的宽度和长度。在view中定义为final类型,要求子类不能修改。measure()函数中又会调用下面的函数:

     (1)onMeasure(),视图大小的将在这里最终确定,也就是说measure只是对onMeasure的一个包装,子类可以覆写onMeasure()方法实现自己的计算视图大小的方式,并通过setMeasuredDimension(width, height)保存计算结果。

2、layout操作

     代码演示:http://www.2cto.com/kf/201511/449947.html

     layout操作用于设置视图在屏幕中显示的位置。在view中定义为final类型,要求子类不能修改。layout()函数中有两个基本操作:

     (1)setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,该函数用于将这些参数保存起来;

     (2)onLayout(),在View中这个函数什么都不会做,提供该函数主要是为viewGroup类型布局子视图用的;

3、draw操作

     draw操作利用前两部得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。子类也不应该修改该方法,因为其内部定义了绘图的基本操作:

     (1)绘制背景;

     (2)如果要视图显示渐变框,这里会做一些准备工作;

     (3)绘制视图本身,即调用onDraw()函数。在view中onDraw()是个空函数,也就是说具体的视图都要覆写该函数来实现自己的显示(比如TextView在这里实现了绘制文字的过程)。而对于ViewGroup则不需要实现该函数,因为作为容器是“没有内容“的,其包含了多个子view,而子View已经实现了自己的绘制方法,因此只需要告诉子view绘制自己就可以了,也就是下面的dispatchDraw()方法;

     (4)绘制子视图,即dispatchDraw()函数。在view中这是个空函数,具体的视图不需要实现该方法,它是专门为容器类准备的,也就是容器类必须实现该方法;

     (5)如果需要(应用程序调用了setVerticalFadingEdge或者setHorizontalFadingEdge),开始绘制渐变框;

     (6)绘制滚动条;

      从上面可以看出自定义View需要最少覆写onMeasure()和onDraw()两个方法。

二、View类的构造方法

创建自定义控件的3种主要实现方式:

1)继承已有的控件来实现自定义控件: 主要是当要实现的控件和已有的控件在很多方面比较类似, 通过对已有控件的扩展来满足要求。

2)通过继承一个布局文件实现自定义控件,一般来说做组合控件时可以通过这个方式来实现。

    注意此时不用onDraw方法,在构造广告中通过inflater加载自定义控件的布局文件,再addView(view),自定义控件的图形界面就加载进来了。

3)通过继承view类来实现自定义控件,使用GDI绘制出组件界面,一般无法通过上述两种方式来实现时用该方式。

三、自定义View增加属性的两种方法:

1)在View类中定义。通过构造函数中引入的AttributeSet 去查找XML布局的属性名称,然后找到它对应引用的资源ID去找值。

案例:实现一个带文字的图片(图片、文字是onDraw方法重绘实现)

public class MyView extends View {
    
    private String mtext;
    private int msrc;

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

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        int resourceId = 0;
        int textId = attrs.getAttributeResourceValue(null, "Text",0);
        int srcId = attrs.getAttributeResourceValue(null, "Src", 0);
        mtext = context.getResources().getText(textId).toString();
        msrc = srcId;
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        InputStream is = getResources().openRawResource(msrc); 
                Bitmap mBitmap = BitmapFactory.decodeStream(is);
                int bh = mBitmap.getHeight();
                int bw = mBitmap.getWidth();
            canvas.drawBitmap(mBitmap, 0,0, paint);
        //canvas.drawCircle(40, 90, 15, paint);
        canvas.drawText(mtext, bw/2, 30, paint);
    }
}

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.example.myimageview2.MyView
        android:id="@+id/myView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        Text="@string/hello_world"
        Src="@drawable/xh"/>

</LinearLayout>

属性Text, Src在自定义View类的构造方法中读取。

2)通过XML为View注册属性。与Android提供的标准属性写法一样。

案例:  实现一个带文字说明的ImageView (ImageView+TextView组合,文字说明,可在布局文件中设置位置)

public class MyImageView extends LinearLayout {

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

    public MyImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        int resourceId = -1;
        TypedArray typedArray = context.obtainStyledAttributes(attrs,
                R.styleable.MyImageView);
        ImageView iv = new ImageView(context);
        TextView tv = new TextView(context);
        int N = typedArray.getIndexCount();
        for (int i = 0; i < N; i++) {
            int attr = typedArray.getIndex(i);
            switch (attr) {
            case R.styleable.MyImageView_Oriental:
                resourceId = typedArray.getInt(
                        R.styleable.MyImageView_Oriental, 0);
                this.setOrientation(resourceId == 1 ? LinearLayout.HORIZONTAL
                        : LinearLayout.VERTICAL);
                break;
            case R.styleable.MyImageView_Text:
                resourceId = typedArray.getResourceId(
                        R.styleable.MyImageView_Text, 0);
                tv.setText(resourceId > 0 ? typedArray.getResources().getText(
                        resourceId) : typedArray
                        .getString(R.styleable.MyImageView_Text));
                break;
            case R.styleable.MyImageView_Src:
                resourceId = typedArray.getResourceId(
                        R.styleable.MyImageView_Src, 0);
                iv.setImageResource(resourceId > 0 ?resourceId:R.drawable.ic_launcher);
                break;   
            }
        }
        addView(iv);
        addView(tv);
        typedArray.recycle();
    }
}

attrs.xml进行属性声明, 文件放在values目录下

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="MyImageView">
        <attr name="Text" format="reference|string"></attr>
        <attr name="Oriental" >
            <enum name="Horizontal" value="1"></enum>
            <enum name="Vertical" value="0"></enum>
        </attr>
        <attr name="Src" format="reference|integer"></attr>
    </declare-styleable>

</resources>

MainActivity的布局文件:先定义命名空间 xmlns:uview="http://schemas.android.com/apk/res/com.example.myimageview2" (com.example.myimageview2为你

在manifest中定义的包名)

然后可以像使用系统的属性一样使用:uview:Oriental="Vertical"

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:uview="http://schemas.android.com/apk/res/com.example.myimageview2"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <com.example.myimageview2.MyImageView
        android:id="@+id/myImageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        uview:Text="这是一个图片说明" 
        uview:Src="@drawable/tw"
        uview:Oriental="Vertical">
    </com.example.myimageview2.MyImageView>

</LinearLayout>

四、控件绘制 onDraw()

五、

六:自定义View的方法

onFinishInflate() 回调方法,当应用从XML加载该组件并用它构建界面之后调用的方法

onMeasure() 检测View组件及其子组件的大小

onLayout() 当该组件需要分配其子组件的位置、大小时

onSizeChange() 当该组件的大小被改变时

onDraw() 当组件将要绘制它的内容时

onKeyDown 当按下某个键盘时

onKeyUp  当松开某个键盘时

onTrackballEvent 当发生轨迹球事件时

onTouchEvent 当发生触屏事件时

onWindowFocusChanged(boolean)  当该组件得到、失去焦点时

onAtrrachedToWindow() 当把该组件放入到某个窗口时

onDetachedFromWindow() 当把该组件从某个窗口上分离时触发的方法

onWindowVisibilityChanged(int): 当包含该组件的窗口的可见性发生改变时触发的方法

Android自定义控件主要流程 创建一个类,继承View类用于计算视图的大小,即视图的宽度和长度。在view中定义为final类型,要求子类不能修改。measure()函数中又会调用下面的函数:onMeasure(),确定视图大小,也就是说measure只是对onMeasure的一个包装,子类可以覆写onMeasure()方法实现自己的计算视图大小的方式,并通过setMeasuredDimension(width, height)保存计算结果。关于MeasureSpec: UPSPECIFIED:父容器对于子容器没有任何限制,子容器想要多 阅读详情

相关推荐

Qt自定义控件以及控件的提升

关于在使用Qt做界面时,通用、常用的控件重复设置属性是件麻烦的事情,比如密码输入框,一个密码输入框要设置许多属性,比如密文显示,长度,只能输入固定字符类型,禁止复制等等,一个项目里面有时会用到很多密码框,每设置一个密码框就会导致对上面的属性重复设置,会导致效率低下,最终规范还不统一等问题。自定义一个控件,继承自QLineEdit类,如下代码: 控件头文件PasswordLineEdit.h#ifn

未来之歌 2万+

Android中级——自定义控件

如下继承TextView@Override//绘制蓝色外层矩形//绘制黄色内层矩形//将文字平移10像素,避免遮挡在其onDraw()绘制文字之前,绘制两个不同的矩形背景,如下当子View上拉超过一定距离,松开后自动滑到下一个子View,下滑同理,布局如下

松仔Log的博客 2615

winform中自定义控件里面的控件随着自定义控件的改变而改变

简单的理解了自定义控件后,才发现,当使用自定义控件的时候,一个很大的问题,里面的控件不会随着自定义控件的改变而改变(包括Size,Font和Location)。上网查了一下,发现这个问题的解决不尽人意。用dock和Anchor都觉得效果不大。

u010030231的专栏 1034

Android 自定义控件

自定义效果,shape定义路径填充的样式,advance是每个图形之间的间距,phase指定偏移量,style分为ROTATE、MORPH和TRANSLATE。如果是一个自定义控件,则需要派生自 View 或其子类,如果是一个自定义的容器,则需要派生自 ViewGroup 或其子类。:设置阴影效果,radius为阴影角度,dx和dy为阴影在x轴和y轴上的距离,color为阴影的颜色。:设置是否使用抗锯齿功能,设置后会平滑一些,但绘制速度会变慢。:设置画笔的颜色,a代表透明度,r,g,b代表颜色值。

weixin_44128558的博客 1101

【安卓自定义控件系列】安卓自定义控件之组合控件

在安卓开发中,谷歌已经为我们提供了许多原生控件,基本上能够满足我们日常的开发需求,但是某些项目中原生控件可能达不到产品所要求的各式各样的酷炫效果或功能效果,这个时候我们只能自己自定义控件来满足项目需求,我们知道自定义控件包括三种方式: 1继承控件,即继承谷歌提供的原生控件,在此基础上提供一些原生控件不具备的功能,如github上各种酷炫效果的开源组件基本上都是采用的这种方式. 2组合控件:即组

(* ̄︶ ̄) 6591

WPF 使用自定义控件库CustomControl实现自定义控件在其他项目使用

WPF 使用自定义控件库CustomControl实现控件在其他项目使用介绍操作流程使用VS2019创建自定义用户控件库在创建的自定义控件项目中添加你的代码生成解决方案并添加到其他WPF项目中 介绍 本文的目的旨在记录在WPF项目中如何使用自定义控件库CustomControlLibrary实现自定义控件在别的 项目使用以及将自定义控件添加到工具箱。 操作流程 使用VS2019创建自定义用户控件库 创建一个新项目,由于我是在.Net FrameWork平台下所以是中文。如果是.Net Core则显示的是

forest_longjiaju的博客 3139

Android自定义控件

通常开发Android应用程序的界面时,都不直接使用View控件,而是使用View控件的子类。例如,如果要显示一段文字,可以使用View控件的子类TextView控件;如果要显示一个按钮,可以使用View控件的子类Button控件。虽然Android提供了很多继承自View类的控件,但是在实际开发中,还会出现不满足需求的情况,此时我们可以通过自定义控件的方式实现。最简单的自定义控件就是创建一个继承View或其子类的类,并重写该类的构造方法。

m0_57150356的博客 1411

HUMAnN 3.0 (alpha)安装及使用

文章目录简介安装数据库下载运行参考 简介 安装 conda install humann humann_test (~1 minute) 数据库下载 humann_databases --download chocophlan full /path/to/databases --update-config yes humann_databases --download uniref uniref90_diamond /path/to/databases --update-config yes humann_

dys的博客 9504

WPF中的用户控件和自定义控件详解

WPF中的用户控件和自定义控件详解

鲤籽鲲的博客 1万+

通达信抓波段指标(主图)

VAR3:=IF(INBLOCK('科创板'),VART20,IF(INBLOCK('创业板') AND DATE>1200823,VART20,IF(INBLOCK('ST板块'),VART5,VART10)));VAR5:=IF(INBLOCK('科创板'),CT20,IF(INBLOCK('创业板') AND DATE>1200823,CT20,IF(INBLOCK('ST板块'),CT5,CT10)));曾涨停/紫色细K线:青字"炸",涨停未封住。曾跌停/蓝色细K线:红字"撬",跌停被打开。

q125500612的博客 2134

【Python&RS】Rasterio库安装+基础函数使用教程

Rasterio是一个Python库,专门用于栅格数据的读写操作。它支持多种栅格数据格式,如GeoTIFF、ENVI和HDF5,为处理和分析栅格数据提供了强大的工具。RasterIO适用于各种栅格数据应用,如卫星遥感、地图制作等。这篇文章跟大家介绍一下Rasterio库的安装以及一些基本函数的使用教程,附带源码。

Remote Sensing迷途小书童 1万+

【3D计算机视觉】从PointNet到PointNet++理论及pytorch代码

从PointNet到PointNet++理论及代码详解1. 点云是什么1.1 三维数据的表现形式1.2 为什么使用点云1.3 点云上以往的相关工作2. PointNet2.1 基于点云的置换不变性2.1.1 由对称函数到PointNet(vanilla)2.1.2 理论证明2.2 基于点云的旋转不变性2.3 网络总体结构2.4 实验结果和网络的鲁棒性2.5 代码解析3. PointNet++3.1...

小执着的博客 8万+

C#自定义控件

自定义控件、扩展控件、复合控件继承Control类扩展控件:继承某个具体的控件类,如:Button,Label等复合控件:继承UserControl类,又称用户控件UserControl。即:把多个控件通过组合的形式,形成更大,功能更全的控件。完全自定义控件继承Control,不是继承UserControl,VS2022中没有提供定义完全自定义控件的模板。1.方法1:通过用户控件,改写成完全自定义控件。2.方法2:通过组件,改写成完全自定义控件。通过用户控件改写后,把错误修复一下即可。

weixin_61819056的博客 1624

QCPColorMap实现瀑布图

QCPColorMap实现真正的瀑布图

pf1873252141的博客 5268

管好 SAP Fiori Launchpad Content:技术目录、业务目录与 KPI 工具的完整治理思路

SAP Fiori Launchpad 作为企业级统一入口,需通过技术目录(源对象)和业务目录(引用编排)分层治理。技术目录由 Launchpad App Manager 维护,负责应用描述对象(Tile 和 Target Mapping)的创建与管理;业务目录由 Launchpad Content Manager 编排,通过引用技术目录对象实现灵活配置。分析型内容则通过 F2814 统一管理。这种分层设计支持应用复用,便于升级维护,是 SAP S/4HANA 项目中实现高效内容治理的关键。

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

Android自定义控件系列——自定义组合控件案例

自定义控件 自定义组合控件 1 创建自定义布局view_combination.xm,指定text的id值 2 创建自定义属性attrs.xml中的resource节点下 &amp;amp;lt;declare-styleable name=&amp;quot;MyView&amp;quot;&amp;amp;gt; //指定MyView为自定义属性名 //设置文本,format的类型见Andrid提示,注意大小写 &amp;amp;lt;attr na

mLuoya的博客 6287

基于STM32+华为云IOT设计的云平台监控系统_102

本次设计结合现代生活的具体需求,设计出一套基于华为云IOT设计的云平台监控系统,可以远程实时查看家里光照强度、温湿度等信息,支持在云端控制家里的电器设备,实现远程控制。

7643

C#自定义控件,在项目工具箱中加入自定义控件,调用自定义控件

本文介绍了在C#中创建和使用自定义控件的完整流程。首先新建Windows控件库项目,添加PictureBox、6个Label和1个Button控件,并设置其属性。通过OpenFileDialog实现图片选择功能,自动计算并显示图片名称、大小(KB)和尺寸(宽×高),同时根据图片大小自动调整显示模式(Zoom或CenterImage)。最后将控件编译为DLL文件,在WinForm项目中引用并调用该自定义控件。整个过程展示了如何扩展基础控件功能,实现特定业务需求,为开发者提供了实用的自定义控件开发范例。

杰西笔记 6482

SimpleITK使用——1. 进行Resample/Resize操作

文章目录1. 变换到一个新的spacing1.1 使用Resample()的方法1.1.1 完整代码1.1.2 转换前后图像1.2 使用ResampleImageFilter()的方法2. 已知原图和变换后目标图像的大小2.1 代码2.2 转换后图像3. 相关内容说明3.0 体素和spacing3.1 Resample() 函数说明3.2 itk::simple::ResampleImageFilter函数说明 1. 变换到一个新的spacing 1.1 使用Resample()的方法 1.1.1

啷个哩个啷 8079

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Qt 自定义控件

你可以继承 QWidget 或者其他现有的 Qt 控件类来创建自定义控件。Q_OBJECTpublic:// 设置控件的初始大小protected:// 绘制事件:自定义按钮的外观// 设置按钮的背景色// 设置文本颜色// 鼠标点击事件:模拟按钮点击// 发射点击信号signals:// 自定义的点击信号Qt 支持使用样式表(QSS)自定义控件的样式,可以在自定义控件中结合 QSS 来设置控件的外观。

qq_43420088的博客 1609

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

用户控件和自定义控件的区别

一.如果现有的   ASP.NET   服务器控件都不符合应用程序的特定要求,则可以创建封装所需功能的   Web   用户控件或   Web   自定义控件。这两种控件之间的主要区别在于设计时的易创建性与易用性。 Web   用户控件易于创建,但它们在高级方案中使用起来可能不太方便。开发   Web   用户控件的方式与开发   Web   窗体页的方式几乎完全相同。与   Web   窗体相似,用户控件可以在可视化设计器中创建,可以使用与   HTML   隔离的代码来编写,并且可以处理执行事件。但是,

johnpeak 7515

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

AWTK自定义控件篇

AWTK 自定义控件篇 一,前序   之前上一篇文章中简单介绍了 AWTK 本身自带的控件(AWTK系统控件篇),但是实际上我们在写一些复杂的 UI 时候, AWTK 本身的控件其实是不够用的,尤其一些特殊的 UI 。这个时候我们该怎样办呢?   现在就引入我们本章节中的自定义控件篇,我们自定义一些控件,给我们专属的程序使用,但是这些自定义的控件最终还是会接入到 AWTK 的体系中,遵循 AWTK...

2601

09 - 高级控件与自定义控件

在 WPF(Windows Presentation Foundation)中,高级控件如 TreeView、ListView 和 DataGrid 提供了强大的功能来显示和操作数据。

weixin_53744371的博客 1004

C#-自定义控件

摘要:本文介绍了C#中创建自定义控件的方法,包括继承现有控件或Control类、重写绘制方法、添加特性和事件处理等步骤。以自定义按钮为例,演示了如何通过继承Button类并重写OnPaint方法实现自定义外观和交互效果。文章还探讨了属性扩展、性能优化等进阶技巧,并指出开发中需注意的性能和兼容性问题。自定义控件能显著提升UI灵活性和用户体验,是C#开发中的重要技能。

2401_84068825的博客 1412

c#自定义控件

123

lajimingzigeshi的博客 1105
上一篇: ActionBar
下一篇: 视频录制
有志青年L
博客等级 码龄10年 30粉丝 59原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值