Android编程中TextView宽度过大导致Drawable无法居中问题解决方法

本文实例讲述了Android编程中TextView宽度过大导致Drawable无法居中问题解决方法。分享给大家供大家参考,具体如下:

在做项目的时候,很多时候我们都要用到文字和图片一起显示,一般设置TextView的DrawableLeft、DrawableRight、DrawableTop、DrawableBottom就行了。但是有一种情况是当TextView的熟悉是fill_parent或者使用权重的时候并且设置了起Gravity的ceter的时候,Drawable图片是无法一起居中的,为了解决其,我们一般再套一层布局,然后设置TextView的熟悉是wrap_content,但是有时候嵌套过多的布局的时候,有可能发生StackOverFlow,所以必须要优化,下面说一下其中的一个解决方案。先上图

这个解决方案很粗糙,局限性很大,文字不能换行,换行之后就不准了,下面是源码:

package com.example.testandroid;
import java.lang.ref.WeakReference;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.TextView;
public class DrawableTextView extends TextView {
 private WeakReference<Bitmap> normalReference;
 private WeakReference<Bitmap> pressReference;
 private WeakReference<Bitmap> showReference;
 private int normalColor = Color.WHITE, pressColor = Color.WHITE;
 private String text;
 private int textWidth = 0;
 private int textHeight = 0;
 public DrawableTextView(Context context) {
  super(context);
 }
 public DrawableTextView(Context context, AttributeSet attrs) {
  super(context, attrs);
 }
 public DrawableTextView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
 }
 @Override
 protected void onFinishInflate() {
  super.onFinishInflate();
  initText();
 }
 private void initText() {
  text = super.getText().toString();
  initVariable();
 }
 /**
  * 初始化,测量Textview内容的长度,高度
  */
 private void initVariable() {
  textWidth = (int) (getPaint().measureText(text));
  final Rect rect = new Rect();
  getPaint().getTextBounds(text, 0, 1, rect);
  textHeight = rect.height();
 }
 /**
  * 设置TextView的内容
  * @param text
  */
 public void setText(String text) {
  this.text = text;
  initVariable();
  invalidate();
 }
 /**
  * 获取TextView内容
  */
 public String getText() {
  return text;
 }
 /**
  * 设置TextView的Drawable内容,目前仅支持DrawableLeft
  * @param normalDrawableId
  *    DrawableLeft的normal状态Id
  * @param pressDrawableId
  *    DrawableLeft的press状态的Id(没有press状态,请传-1)
  */
 public void setDrawableLeftId(final int normalDrawableId, final int pressDrawableId) {
  normalReference = new WeakReference<Bitmap>(BitmapFactory.decodeResource(getResources(), normalDrawableId));
  if (pressDrawableId != -1) {
   pressReference = new WeakReference<Bitmap>(BitmapFactory.decodeResource(getResources(), pressDrawableId));
  }
  showReference = normalReference;
  invalidate();
 }
 /**
  * 设置TextView的Color
  * @param normalColor
  *    TextView normal状态的Color值
  * @param pressDrawableId
  *    TextView press状态的Color值(如果没有press状态,请传与normal状态的值)
  */
 public void setTextColor(final int normalColor, final int pressColor) {
  this.normalColor = normalColor;
  this.pressColor = pressColor;
  getPaint().setColor(normalColor);
  initVariable();
 }
 @Override
 protected void onDraw(Canvas canvas) {
  if (showReference != null && showReference.get() != null) {
   final int bitmapWidth = showReference.get().getWidth();
   final int bitmapHeight = showReference.get().getHeight();
   final int viewHeight = getHeight();
   final int drawablePadding = getCompoundDrawablePadding();
   final int start = (getWidth() - (bitmapWidth + drawablePadding + textWidth)) >> 1;
   canvas.drawBitmap(showReference.get(), start, (viewHeight >> 1) - (bitmapHeight >> 1), getPaint());
   /**
    * 注意改方法,第三个参数y,本人也被误导了好久,原来在画文字的时候,y表示文字最后的位置(不是下笔点的起始位置)
    * 所以为什么 是TextView高度的一半(中间位置) + 文字高度的一半 = 文字居中
    */
   canvas.drawText(text, start + drawablePadding + bitmapWidth, (viewHeight >> 1) + (textHeight >> 1), getPaint());
  }
 }
 @Override
 public boolean onTouchEvent(MotionEvent event) {
  if (event.getAction() == MotionEvent.ACTION_DOWN) {
   if (pressReference != null && pressReference.get() != null) {
    showReference = pressReference;
   }
   getPaint().setColor(pressColor);
  } else if (event.getAction() == MotionEvent.ACTION_UP) {
   if (normalReference != null && normalReference.get() != null) {
    showReference = normalReference;
   }
   getPaint().setColor(normalColor);
  }
  invalidate();
  return super.onTouchEvent(event);
 }
}

xml布局:

<com.example.testandroid.DrawableTextView
android:id="@+id/my_textview"
android:layout_width="fill_parent"
android:layout_marginTop="20dp"
android:background="@drawable/text_selector"
android:drawablePadding="8dp"
android:textColor="@color/standard_orange"
android:layout_height="wrap_content"
android:padding="15dp"
android:textSize="16sp"
android:text="有Drawable的TextView" />

调用代码:

DrawableTextView drawableTextView = (DrawableTextView) getView().findViewById(R.id.my_textview);
drawableTextView.setDrawableLeftId(R.drawable.bg_btn_delete_normal, R.drawable.bg_btn_delete_pressed);
drawableTextView.setTextColor(getResources().getColor(R.color.standard_orange), getResources().getColor(R.color.standard_white));
drawableTextView.setText("我在动态修改Text啦");

其实还有更加方便的方法,下面朋友借鉴某个网友的代码(地址我就不知道了):

@Override
protected void onDraw(Canvas canvas) {
 Drawable[] drawables = getCompoundDrawables();
 if (drawables != null) {
  Drawable drawableLeft = drawables[0];
  if (drawableLeft != null) {
   final float textWidth = getPaint().measureText(getText().toString());
   final int drawablePadding = getCompoundDrawablePadding();
   final int drawableWidth = drawableLeft.getIntrinsicWidth();
   final float bodyWidth = textWidth + drawableWidth + drawablePadding;
   canvas.translate((getWidth() - bodyWidth) / 2, 0);
  }
 }
 super.onDraw(canvas);
}

xml布局:

<com.example.testandroid.DrawableTextView
android:id="@+id/my_textview"
android:layout_width="fill_parent"
android:layout_marginTop="20dp"
android:background="@drawable/text_selector"
android:drawablePadding="8dp"
android:drawableLeft="@drawable/clear_edittext_selector"
android:textColor="@color/text_color_selector"
android:layout_height="wrap_content"
android:padding="15dp"
android:textSize="16sp"
android:text="有Drawable的TextView" />

嗯,自己写这个东西,也学到了一些东西,大家有什么更好的方法,大家可以讨论一下。

希望本文所述对大家Android程序设计有所帮助。

(0)

相关推荐

  • Android 让自定义TextView的drawableLeft与文本一起居中

    前言 TextView的drawableLeft.drawableRight和drawableTop是一个常用.好用的属性,可以在文本的上下左右放置一个图片,而不使用更加复杂布局就能达到,我也常常喜欢用RadioButton的这几个属性实现很多效果,但是苦于不支持让drawbleLeft与文本一起居中,设置gravity为center也无济于事,终于有空研究了一下,这里与大家一起分享. 正文 一.效果图  二.实现代码 自定义控件 /** * drawableLeft与文本一起居中显示 * *

  • Android自定义Drawable实现圆形和圆角

    本文实例为大家分享了自定义Drawable实现圆形和圆角的具体代码,供大家参考,具体内容如下 圆形 package com.customview.widget; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Paint;

  • Android App开发中将View或Drawable转为Bitmap的方法

    View转换为Bitmap Android中经常会遇到把View转换为Bitmap的情形,比如,对整个屏幕视图进行截屏并生成图片:Coverflow中需要把一页一页的view转换为Bitmap.以便实现复杂的图形效果(阴影.倒影效果等):再比如一些动态的实时View为便于观察和记录数据.需要临时生成静态的Bitmap. 实现方法: 1)下面是笔者经常用的一个转换方法 public static Bitmap convertViewToBitmap(View view, int bitmapWid

  • Android Bitmap和Drawable相互转换的简单代码

    很多开发者表示,不知道Android的Drawable和Bitmap之间如何相关转换.下面Android123给大家两种比较简单高效的方法. 一.Bitmap转Drawable 复制代码 代码如下: Bitmap bm=xxx; //xxx根据你的情况获取 BitmapDrawable bd=BitmapDrawable(bm); Android开发网提示因为BtimapDrawable是Drawable的子类,最终直接使用bd对象即可. 二. Drawable转Bitmap 转成Bitmap对

  • 基于android中的各种颜色在drawable.xml中的值详解

    < drawable name="white">#FFFFFF< /drawable>< !--白色 --> < drawable name="black">#000000< /drawable>< !--黑色 --> < drawable name="ivory">#FFFFF0< /drawable>< !--象牙色 --> <

  • android 放大镜ShapeDrawable妙用分享

    首先,ShapeDrawable构造的时候可以指定描画的形状, 其次,可以通过shape.getPaint().setShader();指定Shader,shader可以接受一个图片和matrix 所以问题就顺利的解决了:) 具体实现如下:[java] 复制代码 代码如下: float scale = 1.2f; int cx = 224; int cy = 357; int r = 200; // 指定形状创建一个ShapeDrawable  ShapeDrawable shape=new S

  • Android开发基于Drawable实现圆角矩形的方法

    本文实例讲述了Android开发基于Drawable实现圆角矩形的方法.分享给大家供大家参考,具体如下: 第一步:写个类继承drawable,重写里面的方法,实现的核心代码在draw里 关键技术:BitmapShader public BitmapShader(Bitmap bitmap,Shader.TileMode tileX,Shader.TileMode tileY) 调用这个方法来产生一个画有一个位图的渲染器(Shader). bitmap 在渲染器内使用的位图 tileX The t

  • Android开发使用Drawable绘制圆角与圆形图案功能示例

    本文实例讲述了Android开发使用Drawable绘制圆角与圆形图案功能.分享给大家供大家参考,具体如下: 1. 创建类RoundCircleDrawable继承Drawable /** * 圆角矩形 * @Project App_View * @Package com.android.view.drawable * @author chenlin * @version 1.0 * @Date 2016年4月21日 * @Note TODO */ public class RoundCircl

  • android中图形图像处理之drawable用法分析

    本文实例讲述了android中图形图像处理之drawable用法.分享给大家供大家参考.具体如下: 一.如何获取 res 中的资源 数据包package:android.content.res 主要类:Resources 其主要接口按照功能,划分为以下三部分: getXXXX() 例如: int getColor(int id) Drawable getDrawable(int id) String getString(int id)  直接获取res中存放的资源 InputStream ope

  • 关于Android中drawable必知的一些规则

    前言 一入 Android 深似海,相信很多 Android 开发者深有体会,Android 系统版本的碎片化,Android 硬件设备的多样性,第三方 Rom 的不确定因素.现在想开发一个合格的商业化 App 真的不容易,先不说别的,应用的兼容性就是一项技术和耐心的双重考验,想完美适配各种情况可以说是不可能的,往往都是在人力和适配率之间寻找平衡,今天要说的 drawable 就是需要适配的一个重要角色. 配置限定符 对于不同的屏幕密度.不同的设备方向,不同的语言和区域,都会涉及到备选 draw

  • Android LayerDrawable使用实例

    1.在Android项目开发的时候,经常看到很漂亮的UI界面,比如,当你点击一张图片被选中的时候,覆上一张透明的图片.表示被选中,区别与那些没有被选中的.这种是如何实现的呢?答案是LayerDrawable的使用出现的效果.下面是LayerDrawable的总结,若有不正确的地方,请大家指正. 2.简单的来说,LayerDrawable继承与Drawable,Drawable就是一个可画的对象,可能是一张位图BitmapDrawable,也可能是一个图形ShapeDrawable,还有可能是一个

  • Android自定义Drawable实现圆角效果

    Drawable是一种可绘制资源的载体,如图形.图像等.在实际开发中可以作为view的背景.主要有静态和动态两种方式,静态通过xml描述使用,动态即自定义Drawable.本文实现一个圆形和圆角的背景图片效果. 效果图: 实现方式: 1.初始化一个BitmapShader着色器对象: 2.将着色器对象set给画笔: 3.在画布上绘制圆或圆角即可: 4.使用,view.setBackgroundDrawable 或者 ImageView.setImageDrawable package com.m

随机推荐