当前位置: 首页 > news >正文

【Android】自定义控件

一、什么是自定义控件

自定义控件是指开发者通过继承 Android 系统原有的标准控件(如 TextViewButton)或基础视图类(如 View),通过重写其相关方法,来实现具有特殊外观独特行为封装好的复合功能的视图组件。

简单来说,就是自己动手创造或改造一个现有的UI控件,让它能做标准控件做不到的事情。

当系统提供的标准控件无法满足你的需求时,就需要自定义控件。例如实现特殊的图表(折线图、柱状图、饼图)、非规则形状的按钮(如圆形、星形按钮)等。

二、自定义控件的三种主要方式

2.1继承现有控件

这种方式通过继承 Android 系统提供的标准控件,重写其方法来实现自定义的功能或样式。继承现有控件时,可以复用已有的控件逻辑,同时在此基础上增加额外的功能或样式。

// 示例:一个自动将文本转为大写的TextView
public class UpperCaseTextView extends AppCompatTextView {public UpperCaseTextView(Context context) {super(context);}public UpperCaseTextView(Context context, AttributeSet attrs) {super(context, attrs);}// 重写setText方法,在设置文本前先转成大写@Overridepublic void setText(CharSequence text, BufferType type) {if (text != null) {text = text.toString().toUpperCase();}super.setText(text, type);}
}

2.2组合控件

通过将多个现有控件组合在一起,创建一个新的复合控件。这种方式适用于实现更复杂的 UI 组件,通常涉及多个子控件的组合。通过这种方式,可以轻松创建灵活且富有表现力的控件。

通过继承一个布局(如 LinearLayoutRelativeLayout),在构造函数中inflate( inflate (膨胀,填充)) 一个布局文件,然后找出其中的子View并进行操作和事件封装。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><com.example.applicationui.TitleLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><Buttonandroid:id="@+id/title_back"android:layout_width="50dp"android:layout_height="50dp"/>
​<Buttonandroid:id="@+id/title_edit"android:layout_width="wrap_content"android:layout_height="wrap_content"/></com.example.applicationui.TitleLayout></LinearLayout>
public class TitleLayout extends LinearLayout {public TitleLayout(Context context, AttributeSet attrs){super(context,attrs);LayoutInflater.from(context).inflate(R.layout.title,this);Button titleBack=(Button) findViewById(R.id.title_back);Button titleEdit=(Button) findViewById(R.id.title_edit);titleBack.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {((Activity)getContext()).finish();}});titleEdit.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(getContext(),"Edit",Toast.LENGTH_SHORT).show();}});}
}

2.3继承View

继承 View 或其子类,完全由自己用代码绘制出控件的外观。需要重写 onDraw(Canvas canvas) 方法。


public class CircleView extends View {private Paint mPaint;public CircleView(Context context) {super(context);init();}private void init() {mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(Color.RED);mPaint.setStyle(Paint.Style.FILL); }@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);int centerX = getWidth() / 2;int centerY = getHeight() / 2;int radius = Math.min(centerX, centerY) - 10;canvas.drawCircle(centerX, centerY, radius, mPaint);}
}

三、自定义控件的具体实现步骤

首先,我们需要创建一个继承 View 或其他控件类(如 ButtonTextView 等)的类,并实现必要的方法。

public class MyCustomView extends View {public MyCustomView(Context context) {super(context);}
​public MyCustomView(Context context, AttributeSet attrs) {super(context, attrs);}
​public MyCustomView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}
}
​

之后重写一些关键方法来实现你想要实现的功能或外观。

方法作用常见重写目的
onMeasure(int, int)测量控件自身和其子View的宽高确定控件的最终尺寸
onLayout(boolean, int, int, int, int)布局子View的位置仅在ViewGroup中需要,用于安排子View
onDraw(Canvas)绘制控件的外观实现自绘控件的核心方法
onTouchEvent(MotionEvent)处理触摸事件实现自定义的交互逻辑
dispatchTouchEvent(MotionEvent)分发触摸事件更高级的事件处理和控制

onDraw中使用 Canvas 和 Paint 来绘制控件的背景、文本或其他图形元素。

@Override
protected void onDraw(Canvas canvas) {super.onDraw(canvas);// 绘制控件背景、文本、图形等Paint paint = new Paint();paint.setColor(Color.RED);canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
}
​

如果需要在控件中插入图片,可以获取Bitmap对象

Bitmap weatherIconDay=BitmapFactory.decodeResource(getResources(), R.drawable.cloudy)

之后通过Canvas绘制

 canvas.drawBitmap(weatherIconDay,x,y,null);

如果需要响应用户的交互,可以在onTouchEvent中处理触摸事件,或用 setOnClickListener() 来响应点击事件。

@Override
public boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 处理按下事件break;case MotionEvent.ACTION_MOVE:// 处理移动事件break;case MotionEvent.ACTION_UP:// 处理抬起事件break;}return true;
}
​
http://www.dtcms.com/a/393509.html

相关文章:

  • 探索 Event 框架 6:高级特性与性能优化
  • JavaSE基础——第九章 枚举类注解
  • 云计算在金融领域中的应用
  • 【入门算法】前缀和:先预存再求和,以空间换时间
  • mac编译vst3sdk
  • Java 网络原理(二)--- TCP的机制 + IP协议 +以太网协议 + DNS
  • Python文件名编码处理深度解析:绕过编码问题的专业指南
  • 如何利用简单的浏览器插件Web Scraper爬取知乎评论数据
  • 鹿鼎记豪侠传:Rust 重塑 iOS 江湖(下)
  • 03.博客版-镜像
  • 云原生docker离线二进制安装
  • RabbitMQ 的配置文件位置及常见配置项
  • Visual Prompt Builder-AI 提示词可视化工具
  • 一文掌握Flask:从基础使用到高级应用
  • 23种设计模式之【责任链模式】-核心原理与 Java 实践
  • 执行 conda update -n base -c defaults conda 后仍提示需要升级
  • 学习日报 20250921|NIO
  • 【Linux操作系统】Linux基础指令和权限
  • 谷歌nano banana官方Prompt模板
  • 基于Python大数据的新闻推荐分析
  • ​​[硬件电路-315]:AD7606BSTZ如何测量失调电压?
  • 微服务-分布式追踪 / 监控工具大全
  • The Library: 2靶场渗透
  • 金融知识“厦”乡趣 平安产险厦门分公司启动2025年“金融教育宣传周”活动
  • C++学习笔记——模板初阶
  • Windows 下 WSL2 生态:Ubuntu/Docker Desktop 关系、VLLM 部署差异与性能解析
  • 智能体技术革命:从华为金融智能体FAB看AI智能体的未来发展与行业影响
  • CIKM 2025 | FinCast:用于金融时间序列预测的基础模型
  • 论文解读——矩形隧道中MIMO信道特性的模态理论解释
  • Mac brew VSCode Python3