Android 自定义view-如何设置TextView drawableLeft 图片大小?

      转载自:http://blog.csdn.net/u014702653/article/details/52304656


开发过程中,越发强烈的觉得需要对TextView进一步封装 
1.TextView需要设置背景或者边框时需要编写大量的selector,稍微修改一下样式又得编写一个新的selector,这个实在不能忍! 
2.使用原生TextView的drawableLeft能够减少布局代码,无奈icon大小不能设置,只能眼巴巴找美工切图,我们是一个有节气的程序员,这个也不能忍 
3. 当TextView不同状态下的文本颜色,背景边框等等需要通过Java代码编写乱七八糟的逻辑,为了代码可维护性我们必须要编写一个便于实现这些功能的控件:RTextView

这里写图片描述 这里写图片描述

没错这个就是RTextView的效果,很强大有木有?一个控件搞定所有优美布局的既视感,关键是方便。真的很好用,笔者已经将该控件应用到项目中,看官们可以以不到github了解详情

Github地址https://github.com/RuffianZhong/RTextView


以下内容为原始文章,也是封装控件的最初想法


这里写图片描述

如上图所述,绿色框框中的布局你会怎么实现? 
大概有两种方式解决 
方法1:一个LinearLayout里面放一个ImageView和一个TextView 
方法2:一个TextView然后设置drawableLeft

实现是没有问题,但是我有强迫症,总觉得他们不完美,来说说两种方法的缺点 
方法1:靠,这是什么鬼,不觉得巨麻烦吗?要写三个控件,还要嵌套。要是一行多几个这样的控件,一整个页面得嵌套多少层啊?不行! 
方法2:这个好像不错哦,直接设置drawableLeft(四个方向都行)搞定。但是!这个drawable的大小是不能够通过代码设置大小的!只能叫UI裁剪成合适的图片。卧槽,一定得裁剪到刚好合适?怎么样才合适?看着差不多就好了?所以还是个坑!也不行!

知识是要拿来用的,不是会自定义view吗?那就自己写啊。

需求:text的四周可以设置辅助图标,并且可以设置图标的大小!还要可以设置图片和文字的间距

OK,需求明确了,我一开始想继承RelativeLayout来实现。后来想想TextView都有drawableLeft 之类的属性,肯定可以从这里入手更简单。只要可以改变drawable的大小就好了。

仔细看了TextView相关的API 
1.可以获取到drawable的列表(因为四个方向都可以设置) 
2.但是无法获取到是哪一个方向上设置的drawable 
3.可以通过代码设置drawableLeft 效果

1.自定义View的属性

既然无法获取到是哪一个方向上的drawable,那就自己定义一个方向的属性,并且自己定一个drawable的属性。 
按照需求,属性有:drawable,drawable宽宽,drawable高度,drawable方向 
我们在 /value/attrs.xml 中这么写:

    <!-- RichText -->
    <declare-styleable name="RichText">
        <attr name="drawable_src" format="reference" />
        <attr name="drawable_height" format="dimension" />
        <attr name="drawable_width" format="dimension" />
        <attr name="drawable_location">
            <enum name="left" value="1" />
            <enum name="top" value="2" />
            <enum name="right" value="3" />
            <enum name="bottom" value="4" />
        </attr>
    </declare-styleable>
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.在View的构造方法中获得我们自定义的属性

public class RichText extends TextView {

    public static final int LEFT = 1, TOP = 2, RIGHT = 3, BOTTOM = 4;

    private int mHeight, mWidth;

    private Drawable mDrawable;

    private int mLocation;

    public RichText(Context context) {
        this(context, null);
    }

    public RichText(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.RichText);

        mWidth = a
                .getDimensionPixelSize(R.styleable.RichText_drawable_width, 0);
        mHeight = a.getDimensionPixelSize(R.styleable.RichText_drawable_height,
                0);
        mDrawable = a.getDrawable(R.styleable.RichText_drawable_src);
        mLocation = a.getInt(R.styleable.RichText_drawable_location, LEFT);

        a.recycle();
        //绘制Drawable宽高,位置
        drawDrawable();

    }
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

代码很简单,获取自定义的四个属性值,需要注意的是,这里继承TextView

这里不用重新计算宽高,因为TextView 会帮我们计算,这就是继承自带控件的好处

接下来也不用重写onDraw方法,因为这里没有什么需要绘制的

3.绘制Drawable宽高,位置

接下来直奔主题,直接绘制drawable宽高,位置(相对于text的方向) 
其实关键方法就一个

textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
 
 
  • 1

参数分表代表左,上,右,下。不设置就使用null

靠,写着写着发现好坑哦,就一个关键方法还特意写一篇博客。算了,还是继续写吧。

    /**
     * 绘制Drawable宽高,位置
     */
    public void drawDrawable() {

        if (mDrawable != null) {
            Bitmap bitmap = ((BitmapDrawable) mDrawable).getBitmap();
            Drawable drawable;
            if (mWidth != 0 && mHeight != 0) {

                drawable = new BitmapDrawable(getResources(), getBitmap(bitmap,
                        mWidth, mHeight));

            } else {
                drawable = new BitmapDrawable(getResources(),
                        Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(),
                                bitmap.getHeight(), true));
            }

            switch (mLocation) {
            case LEFT:
                this.setCompoundDrawablesWithIntrinsicBounds(drawable, null,
                        null, null);
                break;
            case TOP:
                this.setCompoundDrawablesWithIntrinsicBounds(null, drawable,
                        null, null);
                break;
            case RIGHT:
                this.setCompoundDrawablesWithIntrinsicBounds(null, null,
                        drawable, null);
                break;
            case BOTTOM:
                this.setCompoundDrawablesWithIntrinsicBounds(null, null, null,
                        drawable);
                break;
            }
        }

    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

这个方法是设置Drawable的宽高和位置。代码很简单。 
判断是否设置了Drawable(别忘了我们本身可是TextView啊) 
如果Drawable不为空,则判断宽高是否设置,如果设置了宽高则绘制成指定的宽高,否则按Drawable原图大小绘制 
根据指定方向在text对应的位置设置Drawable

这里需要注意的是,直接绘制成为指定的宽高,运行效果发现Drawable会被从左上角开始裁剪成为指定的大小。 
所以我们需要根据Drawable原来的大小和目标宽高进行裁剪(缩放)

    /**
     * 缩放图片
     * 
     * @param bm
     * @param newWidth
     * @param newHeight
     * @return
     */
    public Bitmap getBitmap(Bitmap bm, int newWidth, int newHeight) {
        // 获得图片的宽高
        int width = bm.getWidth();
        int height = bm.getHeight();
        // 计算缩放比例
        float scaleWidth = (float) newWidth / width;
        float scaleHeight = (float) newHeight / height;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        // 得到新的图片
        return Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

这样绘制的Drawable才是完整的,按照我们想要的大小缩放后的Drawable

4.布局文件中使用

    <cn.r.richtext.android.widget.RichText
            xmlns:view="http://schemas.android.com/apk/res-auto"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="20dp"
            android:drawablePadding="8dp"
            android:gravity="center"
            android:text="554"
            android:textColor="#FFFFFF"
            view:drawable_height="35dp"
            view:drawable_location="left"
            view:drawable_src="@drawable/preview_comment_icon"
            view:drawable_width="35dp" />
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

恩恩,真正的soeasy!妈妈再也不用担心我嵌套太多布局了。一个控件搞定

这里说明一下,这里是继承TextView所以TextView的所有属性都是可用的, 
比如:设置文字和图标之间的间距( android:drawablePadding=”8dp”) 
比如:如果图标较大,文字的对齐方式( android:gravity=”center”) 
等等,,,


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值