Android定制组件的三种方式

2024-06-18 02:18

本文主要是介绍Android定制组件的三种方式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文地址: http://www.cnblogs.com/baihai/archive/2012/08/20/2647533.html

方式一、继承原有的组件

实例:带图像的TextView

1、IconTextView.java

复制代码
package net.blogjava.mobile.widget;import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.TextView;public class IconTextView extends TextView
{//  命名空间的值private final String namespace = "http://net.blogjava.mobile";//  图像资源IDprivate int resourceId = 0;private Bitmap bitmap;//构造函数public IconTextView(Context context, AttributeSet attrs){//继承TextView的构造函数public TextView(Context context, AttributeSet attrs)super(context, attrs);resourceId = attrs.getAttributeResourceValue(namespace, "iconSrc", 0);if (resourceId > 0)bitmap = BitmapFactory.decodeResource(getResources(), resourceId);}@Overrideprotected void onDraw(Canvas canvas){if (bitmap != null){            //  从原图上截取图像的区域,在本例中为整个图像Rect src = new Rect();//  将截取的图像复制到bitmap上的目标区域,在本例中与复制区域相同Rect target = new Rect();src.left = 0;src.top = 0;src.right = bitmap.getWidth();src.bottom = bitmap.getHeight();int textHeight = (int) getTextSize();target.left = 0;//  计算图像复制到目录区域的纵坐标。由于TextView中文本内容并不是从最顶端开始绘制的,因此,需要重新计算绘制图像的纵坐标target.top = (int) ((getMeasuredHeight() - getTextSize()) / 2) + 1;target.bottom = target.top + textHeight;//  为了保证图像不变形,需要根据图像高度重新计算图像的宽度target.right = (int) (textHeight * (bitmap.getWidth() / (float) bitmap.getHeight()));//  开始绘制图像
            canvas.drawBitmap(bitmap, src, target, getPaint());//  将TextView中的文本向右移动一定的距离(在本例中移动了图像宽度加2个象素点的位置)    canvas.translate(target.right + 2, 0);}super.onDraw(canvas);// 必须最后调用}
}
复制代码

2、main.xml

复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:mobile="http://net.blogjava.mobile" android:orientation="vertical"android:layout_width="fill_parent" android:layout_height="fill_parent"><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第一个笑脸" mobile:iconSrc="@drawable/small" /><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第二个笑脸" android:textSize="24dp" mobile:iconSrc="@drawable/small" /><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第三个笑脸" android:textSize="36dp" mobile:iconSrc="@drawable/small" /><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第四个笑脸" android:textSize="48dp" mobile:iconSrc="@drawable/small" /><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第五个笑脸" android:textSize="36dp" mobile:iconSrc="@drawable/small" /><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第六个笑脸" android:textSize="24dp" mobile:iconSrc="@drawable/small" /><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第七个笑脸" mobile:iconSrc="@drawable/small" /></LinearLayout>  
复制代码

3、效果

 

方式二、组合原有的组件

实例:带文本标签的EditText

1、LabelEditText.java

复制代码
package net.blogjava.mobile.widget;import net.blogjava.mobile.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
import android.widget.TextView;public class LabelEditText extends LinearLayout {private TextView textView;private String labelText;private int labelFontSize;private String labelPosition;public LabelEditText(Context context, AttributeSet attrs) {super(context, attrs);// 读取labelText属性的资源IDint resourceId = attrs.getAttributeResourceValue(null, "labelText", 0);// 未获得资源ID,继续读取属性值if (resourceId == 0)labelText = attrs.getAttributeValue(null, "labelText");// 从资源文件中获得labelText属性的值elselabelText = getResources().getString(resourceId);// 如果按两种方式都未获得labelTex属性的值,表示未设置该属性,抛出异常if (labelText == null) {throw new RuntimeException("必须设置labelText属性.");}// 获得labelFontSize属性的资源IDresourceId = attrs.getAttributeResourceValue(null, "labelFontSize", 0);// 继续读取labelFontSize属性的值,如果未设置该属性,将属性值设为14if (resourceId == 0)labelFontSize = attrs.getAttributeIntValue(null, "labelFontSize", 14);// 从资源文件中获得labelFontSize属性的值elselabelFontSize = getResources().getInteger(resourceId);// 获得labelPosition属性的资源IDresourceId = attrs.getAttributeResourceValue(null, "labelPosition", 0);// 继续读取labelPosition属性的值if (resourceId == 0)labelPosition = attrs.getAttributeValue(null, "labelPosition");// 从资源文件中获得labelPosition属性的值elselabelPosition = getResources().getString(resourceId);// 如果未设置labelPosition属性值,将该属性值设为leftif (labelPosition == null)labelPosition = "left";String infService = Context.LAYOUT_INFLATER_SERVICE;LayoutInflater li;// 获得LAYOUT_INFLATER_SERVICE服务li = (LayoutInflater) context.getSystemService(infService);LinearLayout linearLayout = null;// 根据labelPosition属性的值装载不同的布局文件if ("left".equals(labelPosition))linearLayout = (LinearLayout) li.inflate(R.layout.labeledittext_horizontal, this);else if ("top".equals(labelPosition))linearLayout = (LinearLayout) li.inflate(R.layout.labeledittext_vertical, this);elsethrow new RuntimeException("labelPosition属性的值只能是left或top.");// 下面的代码从相应的布局文件中获得了TextView对象,并根据LabelTextView的属性值设置TextView的属性textView = (TextView) findViewById(R.id.textview);textView.setTextSize((float) labelFontSize);textView.setText(labelText);}}
复制代码

2、main.xml

复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><TextViewandroid:id="@+id/textView"/><net.blogjava.mobile.widget.LabelEditTextandroid:id="@+id/first"android:layout_width="fill_parent"android:layout_height="wrap_content"labelFontSize="16"labelPosition="left"labelText="姓名:" /><net.blogjava.mobile.widget.LabelEditTextandroid:id="@+id/second"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"labelFontSize="26"labelPosition="top"labelText="兴趣爱好" /></LinearLayout>
复制代码

3、labeledittext_horizontal.xml

复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal" android:layout_width="fill_parent"android:layout_height="fill_parent"><TextView android:id="@+id/textview" android:layout_width="wrap_content"android:layout_height="wrap_content" /><EditText android:id="@+id/edittext" android:layout_width="fill_parent"android:layout_height="wrap_content" />
</LinearLayout>
复制代码

4、labeledittext_vertical.xml

复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="fill_parent"android:layout_height="fill_parent"><TextView android:id="@+id/textview" android:layout_width="wrap_content"android:layout_height="wrap_content" /><EditText android:id="@+id/edittext" android:layout_width="fill_parent"android:layout_height="wrap_content" />
</LinearLayout>
复制代码

5、效果

 

方式三、完全重写组件

实例:更换变盘指针后的时钟

1、HandClocl.java

复制代码
package net.blogjava.mobile.widget;import java.util.Calendar;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;public class HandClock extends View implements Runnable {private int clockImageResourceId;private Bitmap bitmap;private float scale;private float handCenterWidthScale;private float handCenterHeightScale;private int minuteHandSize;private int hourHandSize;private Handler handler = new Handler();public void run() {// 重新绘制View
        invalidate();// 重新设置定时器,在60秒后调用run方法handler.postDelayed(this, 60 * 1000);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);// 根据图像的实际大小等比例设置View的大小setMeasuredDimension((int) (bitmap.getWidth() * scale), (int) (bitmap.getHeight() * scale));}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Paint paint = new Paint();paint.setAntiAlias(true);Rect src = new Rect();Rect target = new Rect();src.left = 0;src.top = 0;src.right = bitmap.getWidth();src.bottom = bitmap.getHeight();target.left = 0;target.top = 0;target.bottom = (int) (src.bottom * scale);target.right = (int) (src.right * scale);// 画表盘图像
        canvas.drawBitmap(bitmap, src, target, paint);// 计算表盘中心点的横纵坐标float centerX = bitmap.getWidth() * scale * handCenterWidthScale;float centerY = bitmap.getHeight() * scale * handCenterHeightScale;// 表表盘中心点画一个半径为5的实心圆圈canvas.drawCircle(centerX, centerY, 5, paint);// 设置分针为3个象素粗paint.setStrokeWidth(3);Calendar calendar = Calendar.getInstance();int currentMinute = calendar.get(Calendar.MINUTE);int currentHour = calendar.get(Calendar.HOUR);// 计算分针和时间的角度double minuteRadian = Math.toRadians((360 - ((currentMinute * 6) - 90)) % 360);double hourRadian = Math.toRadians((360 - ((currentHour * 30) - 90)) % 360 - (30 * currentMinute / 60));// 在表盘上画分针canvas.drawLine(centerX, centerY, (int) (centerX + minuteHandSize * Math.cos(minuteRadian)), (int) (centerY - minuteHandSize * Math.sin(minuteRadian)), paint);// 设置实针为4个象素粗paint.setStrokeWidth(4);// 在表盘上画分针canvas.drawLine(centerX, centerY, (int) (centerX + hourHandSize * Math.cos(hourRadian)), (int) (centerY - hourHandSize * Math.sin(hourRadian)), paint);}public HandClock(Context context, AttributeSet attrs) {super(context, attrs);// 读取相应的属性值clockImageResourceId = attrs.getAttributeResourceValue(null, "clockImageSrc", 0);if (clockImageResourceId > 0)bitmap = BitmapFactory.decodeResource(getResources(), clockImageResourceId);scale = attrs.getAttributeFloatValue(null, "scale", 1);handCenterWidthScale = attrs.getAttributeFloatValue(null, "handCenterWidthScale", bitmap.getWidth() / 2);handCenterHeightScale = attrs.getAttributeFloatValue(null, "handCenterHeightScale", bitmap.getHeight() / 2);// 在读取分针和时针长度后,将其值按图像的缩放比例进行缩放minuteHandSize = (int) (attrs.getAttributeIntValue(null, "minuteHandSize", 0) * scale);hourHandSize = (int) (attrs.getAttributeIntValue(null, "hourHandSize", 0) * scale);int currentSecond = Calendar.getInstance().get(Calendar.SECOND);// 将定时器设在0分时执行run方法handler.postDelayed(this, (60 - currentSecond) * 1000);}@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();// 删除回调类handler.removeCallbacks(this);}}
复制代码

完整代码:http://pan.baidu.com/share/link?shareid=22336&uk=1829692564

这篇关于Android定制组件的三种方式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1071033

相关文章

如何突破底层思维方式的牢笼

我始终认为,牛人和普通人的根本区别在于思维方式的不同,而非知识多少、阅历多少。 在这个世界上总有一帮神一样的人物存在。就像读到的那句话:“人类就像是一条历史长河中的鱼,只有某几条鱼跳出河面,看到世界的法则,但是却无法改变,当那几条鱼中有跳上岸,进化了,改变河道流向,那样才能改变法则。”  最近一段时间一直在不断寻在内心的东西,同时也在不断的去反省和否定自己的一些思维模式,尝试重

轻量级在线服装3D定制引擎Myway简介

我写的面向web元宇宙轻量级系列引擎中的另外一个,在线3D定制引擎Myway 3D。 用于在线商品定制,比如个性化服装的定制、日常用品(如杯子)、家装(被套)等物品的在线定制。 特性列表: 可更换衣服款式,按需定制更换模型可实时更改材质颜色可实时添加文本,并可实时修改大小、颜色和角度,支持自定义字体可实时添加艺术图标,并可实时修改大小、颜色和角度,支持翻转、各种对齐可更改衣服图案,按需求定制

idea lanyu方式激活

访问http://idea.lanyus.com/这个地址。根据提示将0.0.0.0 account.jetbrains.com添加到hosts文件中,hosts文件在C:\Windows\System32\drivers\etc目录下。点击获得注册码即可。

公共筛选组件(二次封装antd)支持代码提示

如果项目是基于antd组件库为基础搭建,可使用此公共筛选组件 使用到的库 npm i antdnpm i lodash-esnpm i @types/lodash-es -D /components/CommonSearch index.tsx import React from 'react';import { Button, Card, Form } from 'antd'

React+TS前台项目实战(十七)-- 全局常用组件Dropdown封装

文章目录 前言Dropdown组件1. 功能分析2. 代码+详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇主要讲全局Dropdown组件封装,可根据UI设计师要求自定义修改。 Dropdown组件 1. 功能分析 (1)通过position属性,可以控制下拉选项的位置 (2)通过传入width属性, 可以自定义下拉选项的宽度 (3)通过传入classN

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

android 免费短信验证功能

没有太复杂的使用的话,功能实现比较简单粗暴。 在www.mob.com网站中可以申请使用免费短信验证功能。 步骤: 1.注册登录。 2.选择“短信验证码SDK” 3.下载对应的sdk包,我这是选studio的。 4.从头像那进入后台并创建短信验证应用,获取到key跟secret 5.根据技术文档操作(initSDK方法写在setContentView上面) 6.关键:在有用到的Mo

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

Android我的二维码扫描功能发展史(完整)

最近在研究下二维码扫描功能,跟据从网上查阅的资料到自己勉强已实现扫描功能来一一介绍我的二维码扫描功能实现的发展历程: 首页通过网络搜索发现做android二维码扫描功能看去都是基于google的ZXing项目开发。 2、搜索怎么使用ZXing实现自己的二维码扫描:从网上下载ZXing-2.2.zip以及core-2.2-source.jar文件,分别解压两个文件。然后把.jar解压出来的整个c

android 带与不带logo的二维码生成

该代码基于ZXing项目,这个网上能下载得到。 定义的控件以及属性: public static final int SCAN_CODE = 1;private ImageView iv;private EditText et;private Button qr_btn,add_logo;private Bitmap logo,bitmap,bmp; //logo图标private st