今天在做一个界面的时候,碰到了一个需求是要在一个文字旁边放一个小图标,
本来想用一个TextView和一个ImageView横向布局然后作为一个整体来做,但是我发现有很多地方有着这样的小按钮,(图片+文字的形式),所以本着怎么懒怎么写的原则,就想找有没有更简洁一点的办法,比如能不能再TextView中添加一个图标呢,随便输入一个drawable以后,自动出现了很多如下属性:
一看这应该是添加图片的,再随便添加一个,发现真的把图片加上来了.但是我们又发现,添加图片的属性就那么四个drawableTop,drawableBottom,drawableLeft,drawableRight 意思分别是将图片添加到文字的上,下,左,右侧,这也挺方便的,而且也发现还能随着父元素的大小来设置图片的大小.但是发现里面有一个按钮是TextView中没有文字,只想加一个图标,就会发现用这几个方法以后,图标会在边框里面上下左右对齐,没办法居中.这还不是重点, 重点是我没办法设置图片的尺寸,可能我可以去设置父元素的padding,但是这时候会将文字一起压缩了.
这时候我又去苦苦寻找看看有没有办法设置这个图标自己的padding,发现里面有一个
这个属性,当时以为是用来设置图标的padding的,最后试了一下,发现这个值只会影响图片和文字之间的距离,另外三边的padding则不会设置. 所以最后苦寻无果后,只能继续百度看看怎么设置TextView的图片,网上一大片都是说自定义TextView,那好吧,自定义一个TextView.
先将最后完成的代码交上,然后说一下在定义这个View中间发生的问题:
1.这是自定义view中需要自定义的属性文件:
<!--图片按钮-->
<declare-styleable name="RichText">
<attr name="drawableSrc" format="reference" />
<attr name="drawableWidth" format="dimension" />
<attr name="drawableHeight" format="dimension" />
<attr name="drawableLocation">
<enum name="left" value="1" />
<enum name="top" value="2" />
<enum name="right" value="3" />
<enum name="bottom" value="4" />
</attr>
</declare-styleable>
2.继承自TextView
@SuppressLint("AppCompatCustomView")
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) {
this(context, attrs, 0);
}
public RichText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RichText, defStyleAttr, 0);
mDrawable = array.getDrawable(R.styleable.RichText_drawableSrc);
mWidth = array.getDimensionPixelSize(R.styleable.RichText_drawableWidth, 0);
mHeight = array.getDimensionPixelSize(R.styleable.RichText_drawableHeight, 0);
mLocation = array.getIndex(R.styleable.RichText_drawableLocation);
array.recycle();
drawDrawable();
}
public void drawDrawable() {
if (mDrawable != null) {
Bitmap bitmap = ((BitmapDrawable) mDrawable).getBitmap();
Drawable drawable;
if (mWidth != 0 && mHeight != 0) {
drawable = new BitmapDrawable(getResources(), ImageUtils.getBitmap(bitmap, mWidth, mHeight));
} else {
drawable = new BitmapDrawable(getResources(),
Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(),
bitmap.getHeight(), true));
}
//在代码中设置组件的drawable的时候如果单纯的使用setCompoundDrawables是不会有效果的,
// 因为没有指定drawable的大小,即Bound,具体代码如下:
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
switch (mLocation) {
case LEFT:
Log.i("TAG", "添加在左边");
setCompoundDrawables(drawable, null, null, null);
break;
case TOP:
Log.i("TAG", "添加在顶部");
setCompoundDrawables(null, drawable, null, null);
break;
case RIGHT:
Log.i("TAG", "添加在右侧");
setCompoundDrawables(null, null, drawable, null);
break;
case BOTTOM:
Log.i("TAG", "添加在底部");
setCompoundDrawables(null, null, null, drawable);
break;
}
}
}
}
3.布局文件:
<com.example.loomc.myapplication.weight.RichText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/radio_button"
android:gravity="center"
android:paddingBottom="2dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="2dp"
android:textSize="@dimen/font_size1"
app:drawableHeight="20dp"
app:drawableLocation="left"
app:drawableSrc="@mipmap/icon_male"
app:drawableWidth="20dp" />
上面三个就是自定义这个图片TextView用到的
下面就来说一下中间遇到的问题.之前在没有解决问题之前,我定义的View的图片是怎么都没有显示出来的.
问题1.当时自定义的TextView的类名叫做ImageTextView
但是,属性文件中declare-styleable name=“RichText”
name属性设置为RichText跟类名不一样,最后出现的情况就是在布局文件去获取属性的时候,IDE就是没办法自动弹出我定义的这个类View的属性名,而且又在命名空间这里卡了好久,因为他老是提示我用view: 这个标签,但是我在前面定义的view好像自定义属性都是用app:这个标签来调用的,最后各种百度,就是没找到,我也不知道是啥原因,强迫症的我就是想把这个问题解决掉,我就去看之前定义的view跟我这个定义的view有什么区别,最后不懈努力加上灵光一闪,把这个declare-styleable name=“RichText” 中的name参数改成自定义View的类名一样的名字,发现果然就可以让IDE自动的显示出来,就是类似下图中的提示方式,之前是怎么都没有这几个属性的.而且打日志的时候mWidth,mDrawable等值都是获取不到的,所以这里肯定是获取自定义属性的时候出了问题,没有获取到.
解决完这个问题后,图片还是没有显示.继续
问题2.自定义View中,我用的也是很传统的三个构造函数内部调用,的方式,然后view的初始化或者显示的任务都放在最后一个构造函数中.
貌似这里也没有啥问题,然后我用Log.i()打日志的方式,查看这时候mWidth这些值都是有的,mDrawable也获取到了,说明图片是设置进来了,但是为啥显示不了.弄了一个下午,快绝望了,
程序到这里的时候,drawable是获取到了而且尺寸也都有,我就想呀,这图片都有,再怎么,你也要在界面显示一点点出来呀,可是毛都没有,后面就只剩一个方法了,
可这个方法是Android自己的,出问题也不可能是那里面出问题了吧,所以我一直就没去调查那个方法,一直在看我前面是不是出了什么问题,最后到了这里没办法,只好来看看这个方法是干嘛的,其实这个方法前面我也了解了,就是在周围添加图片的功能,方法四个参数分别是左上右下.后来就百度了一下
“setcompounddrawables 不显示” 发现网上很多这个问题,我一下惊喜了,心里有预感就是这里出问题了,说不定是我哪里没有配置,所以才会导致这个方法没起作用(当然肯定不是这个方法有问题了,这还是有自知之明的).找了几个终于找到关键点了,也是我在代码中注释好的那句话:“在代码中设置组件的drawable的时候如果单纯的使用setCompoundDrawables是不会有效果的”
所以在调用setcompounddrawables ()这个方法之前加了一句drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
这个方法就是对drawable进行设置宽高,心里想这下百分之九十应该是可以看到我的图标出来了,打开视图一看,果然出来了,所以就来这里把这个问题记录了一下