首页 > 其他分享 >自定义Android组件之带图像的TextV…

自定义Android组件之带图像的TextV…

时间:2023-07-31 22:02:24浏览次数:37  
标签:之带 自定义 命名 TextV 图像 组件 android TextView 属性

本文为新书《Android/OPhone开发完全讲义》的内容连载。《Android/OPhone开发完全讲义》一书将在近期出版,敬请关注。

 Android系统支持的图像格式)的TextView组件。在编写代码之前,先看一下Android组件的配置代码。


1. <TextView android:id="@+id/textview1" android:layout_width="fill_parent"
2.        android:layout_height="wrap_content" android:text="textview1"
3. />

复制代码



上面的代码配置了一个标准的TextView组件。在这段代码中主要有两部分组成:组件标签(<TextView>)和标签属性(android:id、android:layout_width等)。需要注意的是,在所有的标签属性前面都需要加了一个命名空间(android)。实际上,android命名空间的值是在Android系统中预定义的,所有Android系统原有的组件在配置时都需要在标签属性前加android。
   3种选择。
    1.  仍然沿用android命名空间。
    2.  改用其他的命名空间。
    3.  不使用命名空间。

虽然上面3种选择从技术上说都没有问题,但作者建议使用第2种方式(尤其是对外发布的组件),这是因为在使用定制组件时,可能需要指定相同名称的属性,在这种情况下,可以通过命名空间来区分这些属性,例如,有两个命名空间:android和mobile,这时可以在各自的命名空间下有相同名称的属性,如android:src和mobile:src。在本例中定义了一个mobile命名空间,因此,在配置本例实现的组件时需要在属性前加mobile。
    实现定制组件的一个重要环节就是读取配置文件中相应标签的属性值,由于本例要实现的组件类需要从TextView类继承,因此,只需要覆盖TextView类中带AttributeSet类型参数的构造方法即可,该构造方法的定义如下:
[code=java]public TextView(Context context, AttributeSet attrs)[/code]在构造方法中可以通过AttributeSet接口的相应getter方法来读取指定的属性值,如果在配置属性时指定了命名空间,需要在使用getter方法获得属性值时指定这个命名空间,如果未指定命名空间,则将命名空间设为null即可。
IconTextView是本例要编写的组件类,该类从TextView继承,在onDraw方法中将TextView中的文本后移,并在文本的前方添加了一个图像,该图像的资源ID通过mobile:iconSrc属性来指定。IconTextView类的代码如下:

1. package net.blogjava.mobile.widget;
2. 
3. import android.content.Context;
4. import android.graphics.Bitmap;
5. import android.graphics.BitmapFactory;
6. import android.graphics.Canvas;
7. import android.graphics.Rect;
8. import android.util.AttributeSet;
9. import android.widget.TextView;
10. 
11. public
12. class IconTextView extends TextView
13. {
14.    //  命
15. 名
16. 空间的值
17.    private final String namespace =  "http://net.blogjava.mobile";
18.    //  保
19. 存
20. 图像资源ID的变量
21.    private int resourceId =0;
22.    private Bitmap bitmap;
23.    public IconTextView(Context context, AttributeSet attrs)
24.    {
25.        super(context, attrs);
26.        //  getAttributeResourceValue 方
27. 法
28. 用来获得组件属性的值,在本例中需要通过该方法的第1个参数指
29.         //  定命名空间的值。该方法的第2个参数表示组件属性名
30. (不
31. 包括命名空间名称),第3个参数表示默
32.         //  认值,也就是如果该属性不存在,则返回第3个参数指定的值
33.        resourceId = attrs.getAttributeResourceValue(namespace, "iconSrc", 0);
34.        if (resourceId > 0)
35.              //  如
36. 果
37. 成功获得图像资源的ID,装载这个图像资源,并创建Bitmap对象
38.            bitmap = BitmapFactory.decodeResource(getResources(), resourceId);
39.       }
40. @Override
41. protected void onDraw(Canvas canvas)
42. {
43.        if (bitmap != null)
44.        {
45.            //  从
46. 原
47. 图上截取图像的区域,在本例中为整个图像
48.            Rect src = new Rect();
49.            //  将
50. 截
51. 取的图像复制到bitmap上的目标区域,在本例中与复制区域相同
52.            Rect target = new Rect();
53.            src.left = 0;
54.            src.top = 0;
55.            src.right = bitmap.getWidth();
56.            src.bottom = bitmap.getHeight();
57.            int textHeight = (int) getTextSize();
58.            target.left = 0;
59.            //  计
60. 算
61. 图像复制到目标区域的纵坐标。由于 TextView组件的文本内容并不是
62.              //  从最顶端开始绘制的,因此,需
63. 要
64. 重新计算绘制图像的纵坐标
65.            target.top = (int) ((getMeasuredHeight() - getTextSize()) / 2) + 1;
66.            target.bottom = target.top + textHeight;
67.            //  为
68. 了
69. 保证图像不变形,需要根据图像高度重新计算图像的宽度
70.            target.right = (int) (textHeight * (bitmap.getWidth() / (float) bitmap.getHeight()));
71.            //  开
72. 始
73. 绘制图像
74.            canvas.drawBitmap(bitmap, src, target, getPaint());
75.            //  将
76. TextView
77. 中的文本向右移动一定的距离(在本例中移动了图像宽度加2个象素点的位置)
78.            canvas.translate(target.right + 2, 0);
79.        }
80.        super.onDraw(canvas);
81.    }
82. }

复制代码



在编写上面代码时需要注意如下3点:
1.  需要指定命名空间的值。该值将在<LinearLayout>标签的xmlns:mobile属性中定义。
2.  如果在配置组件的属性时指定了命名空间,需要在AttributeSet 接口的相应getter方法中的第1个参数指定命名空间的值,而第2个参数只需指定不带命名空间的属性名即可。
3.  TextView类中的onDraw方法一定要在translate方法后面执行,否则系统不会移动TextView中的文本。

下面在main.xml文件中配置了7个IconTextView组件,分别设置了不同的字体大小,同时,文本前面的图像也会随着字体大小的变化而放大或缩小,配置代码如下:

1. <?xml version="1.0" encoding="utf-8"?>
2.  在
3. 下
4.  -->
5. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
6.    xmlns:mobile="http://net.blogjava.mobile" android:orientation="vertical"
7.    android:layout_width="fill_parent" android:layout_height="fill_parent">
8.  mobile:iconSrc
9. 是
10. 可选属性,如果未设置该属性,则IconTextView与TextView的效果相同  -->
11. <!-- 由于
12. IconTextView
13. 和Main类不在同一个包中,因此,需要显式指定package -->
14.  <net.blogjava.mobile.view.IconTextView
15.        android:layout_width="fill_parent" android:layout_height="wrap_content"
16.        android:text=" 第
17. 一
18. 个笑脸" mobile:iconSrc="@drawable/small"
19. />
20.  <net.blogjava.mobile.widget.IconTextView
21.        android:layout_width="fill_parent" android:layout_height="wrap_content"
22.        android:text=" 第
23. 二
24. 个笑脸" android:textSize="24dp" mobile:iconSrc="@drawable/small"
25. />
26.  <net.blogjava.mobile.widget.IconTextView
27.        android:layout_width="fill_parent" android:layout_height="wrap_content"
28.        android:text=" 第
29. 三
30. 个笑脸" android:textSize="36dp" mobile:iconSrc="@drawable/small"
31. />
32.  <net.blogjava.mobile.widget.IconTextView
33.        android:layout_width="fill_parent" android:layout_height="wrap_content"
34.        android:text=" 第
35. 四
36. 个笑脸" android:textSize="48dp" mobile:iconSrc="@drawable/small"
37. />
38.  <net.blogjava.mobile.widget.IconTextView
39.        android:layout_width="fill_parent" android:layout_height="wrap_content"
40.        android:text=" 第
41. 五
42. 个笑脸" android:textSize="36dp" mobile:iconSrc="@drawable/small"
43. />
44.  <net.blogjava.mobile.widget.IconTextView
45.        android:layout_width="fill_parent" android:layout_height="wrap_content"
46.        android:text=" 第
47. 六
48. 个笑脸" android:textSize="24dp" mobile:iconSrc="@drawable/small"
49. />
50.  <net.blogjava.mobile.widget.IconTextView
51.        android:layout_width="fill_parent" android:layout_height="wrap_content"
52.        android:text=" 第
53. 七
54. 个笑脸" mobile:iconSrc="@drawable/small"
55. />
56. </LinearLayout>


复制代码


运行本实例后,将显示如图1所示的效果。

自定义Android组件之带图像的TextV…_命名空间


注意:虽然很多人认为组件的属性必须以android命名空间开头,该命名空间的值必须是http://schemas.android.com/apk/res/android。实际上,只是命名空间的值必须是http://schemas.android.com/apk/res/android而已,命名空间的名称可以是任何值,如下面的代码所示:

1. <?xml version="1.0" encoding="utf-8"?>
2.  将
3. android
4.  -->
5. <LinearLayout xmlns:abcd="http://schemas.android.com/apk/res/android"
6.    abcd:orientation="vertical" abcd:layout_width="fill_parent"
7.    abcd:layout_height="fill_parent">
8. 
9. </LinearLayout>

标签:之带,自定义,命名,TextV,图像,组件,android,TextView,属性
From: https://blog.51cto.com/u_3124497/6913790

相关文章

  • 关于自定义程序打包成jar包,并读取配置
    前言在实际开发过程中,我们有时候有把你编写的一段程序打成jar包的需求,而一些配置是需要去配置文件里面读取关于这项目的一些配置,本人在网络上查询了众多的资料,总的来说可以归为3类1.从数据库读取配置 老生常谈,在dao层从数据库获取配置信息,然后返回到Service层进行业务逻辑......
  • 获取yml自定义内容的方式
    yml内容yml:login:name:zhangsanage:18pass:123456方式一:创建实体类@Configuration@ConfigurationProperties(prefix="yml.login")@DatapublicclassYmlVo{privateStringname;privateStringage;privateStringpas......
  • echarts 自定义提示框
    consttooltip=(params,echartsBarData)=>{constresult=params.map((item,index)=>{conststr=item.name.substring(0,1);if(echartsBarData[index].drugNameCosList){constdata=echartsBarData[index].drugNameCosList.filter(......
  • react18 hooks自定义移动端Popup弹窗组件RcPop
    基于React18Hooks实现手机端弹框组件RcPopreact-popup基于react18+hook自定义多功能弹框组件。整合了msg/alert/dialog/toast及android/ios弹窗效果。支持20+自定义参数、组件式+函数式调用方式,全方位满足各种弹窗场景需求。引入组件在需要使用弹窗的页面引入组件。//引......
  • Manacher模板,支持自定义不同字符的相等关系
    #include<bits/stdc++.h>usingnamespacestd;structManacher{  structChar{    charch;    Char(){}    Char(charch):ch(ch){}    Char&operator=(constchar&r){      ch=r;      ret......
  • 通过Redis+Mysql来自定义Spring-Statemachine的持久化
    我们在使用Spring状态机的时候,往往需要对于StateMachine持久化操作,但是官方为我们提供的基于redis的持久化并不是特别好,一方面是因为只存redis容易导致数据丢失,另一方面因为状态机的特性需要对应的StateMachine的数据永久有效,导致redis中的key永不过期。我现在希望实现将StateMac......
  • springboot logback 配置文件 自定义logback配置文件
    logging:level:#配置全部的调试级别#root:trace#配置具体包路径下的调试级别com.example.springboot03:tracepattern:#默认控制台输出格式console:'%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-ddHH:mm:ss.SSSXXX}}){faint}%clr(${LOG_......
  • .Net Core中自定义认证实现
    一、起因 (原文)最近项目中需要对项目同时支持JWT认证,以及自定义的认证校验方式认证。通过对官方文档了解,得到认证实现主要通过继承 IAuthenticationHandler 或 AuthenticationHandler<TOptions>来实现自定义认证的处理。那么接下来实现一个自定义的认证访问。二、......
  • 【go语言】2.4.2 自定义包的创建和使用
    在Go中,任何一个目录都可以被视为一个包。创建自定义包的基本步骤是:新建一个目录,用于存放包的源文件。在新建的目录中编写Go代码,代码的第一行应该是 package包名。使用 import 语句在其他地方导入和使用这个包。接下来,我们详细看一下如何创建和使用自定义包。创建自......
  • .NET Core 6.0 配置自定义JWT鉴权
    JWT授权配置1、安装Microsoft.IdentityModel.Tokens包;2、创建一个认证用户信息实体类UserInfo3、创建一个JWT配置类JWTTokenOptions   publicclassJwtTokenOptions   {       ///<summary>       ///JWT认证Key       ///</sum......