zoukankan      html  css  js  c++  java
  • 新书内容连载(1):自定义Android组件之带图像的TextView

    本文为原创,如需转载,请注明作者和出处,谢谢!

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

    购 买:互动网

    《Android/OPhone 开发完全讲义》目录

    源代码下载


        在本例中要实现一个可以在文本前方添加一个 图像(可以是任何Android系统支持的图像格式)的TextView组件。在编写代码之前,先看一下Android组件的配置代码。

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

         在构造方法中可以通过AttributeSet接口的相应getter方法来读取指定的属性值,如果 在配置属性时指定了命名空间,需要在使用getter方法获得属性值时指定这个命名空间,如果未指定命名空间,则将命名空间设为null即可。

        IconTextView是本例要编写的组件类,该类从TextView继承,在onDraw方法中将TextView中的文本后移,并在文本的前方添加了一个图像,该图像的资源ID通过mobile:iconSrc属性来指定。IconTextView类的代码如下:

    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";
        
    //  保存图像资源ID的变量
        private int resourceId = 0;
        
    private Bitmap bitmap;
        
    public IconTextView(Context context, AttributeSet attrs)
        {
            
    super(context, attrs);
            
    //  getAttributeResourceValue方法用来获得组件属性的值,在 本例中需要通过该方法的第1个参数指
             
    //  定命名空间的值。该方法的第2个参数表示组件属性名(不包括命名空间名称),第3个 参数表示默
             
    //  认值,也就是如果该属性不存在,则返回第3个参数指定的值
            resourceId = attrs.getAttributeResourceValue(namespace, "iconSrc"0);
            
    if (resourceId > 0)
                  
    //  如果成功获得图像资源的ID,装载这个图像资源,并创建Bitmap对象
                bitmap = BitmapFactory.decodeResource(getResources(), resourceId);
        }
        @Override
        
    protected 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 + 20);
            }
            
    super.onDraw(canvas);
        }
    }

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

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

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

    <?xml version="1.0" encoding="utf-8"?>
    <!--  将android换成了abcd  -->
    <LinearLayout xmlns:abcd="http://schemas.android.com/apk/res/android"
        abcd:orientation
    ="vertical" abcd:layout_width="fill_parent"
        abcd:layout_height
    ="fill_parent">
         
    </LinearLayout>

     
    下一篇:新书内容连载(2):Android Activity的生命周期

  • 相关阅读:
    如何将 Python 程序打包成 .exe 文件?
    无穷滚动(Infinite scroll)的实现原理
    图片延迟加载(lazyload)的实现原理
    Java 基础 -- 泛型、集合、IO、反射
    Ubuntu on win10
    让自己少走点弯路
    使用MongoDB 记录业务日志
    19个JavaScript数组常用方法总结
    Kubernetes 使用Nginx-Ingress实现蓝绿发布/金丝雀发布/AB测试
    官方golang包管理神器
  • 原文地址:https://www.cnblogs.com/nokiaguy/p/1723497.html
Copyright © 2011-2022 走看看