一般当我们要实现文本旁边加一个图片的效果时(比如一般底部的导航栏都是这么个效果),经常会用一个TextView和一个ImageView组合来实现,当要改变状态时要显示不一样的背景或者颜色,同时Image也要变化。这样一来,效果是实现了,可是弊端在于,不只是xml端的代码很冗余(除了空间组合多,而且定义的用于状态切换的selector也多),而且代码端的更麻烦,你要在合适的时机去动态的改变,势必会频繁地setSelected()、setEnable(),想想就很乱。
所以,我们找到了drawableLeft、drawableRight、drawableTop、drawableBottom这几个属性,我们可以方便的在一个控件下实现图片为文本同时显示的效果,而且动态的改变变得更加简便和便于维护,可是并没有什么完美的东西,他的缺点就是,我们不能去改变他这个drawable的大小,所以当我们的drawable的宽度或者高度比TextView大的时候就会只显示一部分,我们能做的只有先把图片一开始就做成控件所能适应的大小,这样一来,UI会疯的
,因为在一切落实之前,布局可能会频繁的改动的。如果你说我可以把UI的图拿过来自己用某软件缩成我需要的,那么你只是把UI的工作量挪到了自己这边,似不似傻,我就这么傻过(那是我刚工作的时候,一切为别人考虑...)。关键是即便是这样你在程序中显示出来的图片和UI给你的相比是失真的,你会看到一片片的朦胧美,然后我当时就懵逼了...
现在对于这个问题我们有了可以说是完美的解决方法:自定义View!
首先,定义我们自己的属性
其次,写一个继承自TextView的View,实现他的构造方法
public class DrawableTextView extends TextView {
public static final String TAG = Contacts.TAG ;
public static final int LEFT=1,TOP=2,RIGHT=3,BOTTOM=4 ;
private Drawable src ;
private int drawablePosition ;
private int drawableWidth ;
private int drawableHeight ;
private Bitmap mBitmap;
public DrawableTextView(Context context) {
super(context);
}
public DrawableTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DrawableTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.DrawableTextView,defStyleAttr,0);
//默认设置为“college”图片
src = array.getDrawable(R.styleable.DrawableTextView_drawableSrc);
Log.d(TAG, "DrawableTextView: "+src);
//默认设置为左边
drawablePosition = array.getInt(R.styleable.DrawableTextView_drawablePosition, LEFT);
Log.d(TAG, "DrawableTextView: "+drawablePosition);
//默认为20dp宽
drawableWidth = array.getDimensionPixelSize(R.styleable.DrawableTextView_drawableWidth,0);
Log.d(TAG, "DrawableTextView: "+drawableWidth);
//默认为20dp长
drawableHeight = array.getDimensionPixelSize(R.styleable.DrawableTextView_drawableHeight,0);
Log.d(TAG, "DrawableTextView: " + drawableHeight);
array.recycle();
drawDrawable();
}
private void drawDrawable() {
if (src != null) {
Bitmap bitmap = ((BitmapDrawable)src).getBitmap();
Drawable drawable ;
if (drawableWidth!=0&&drawableHeight!=0) {
drawable = new BitmapDrawable(getResources(),getBitmap(bitmap,drawableWidth,drawableHeight));
}else {
drawable = new BitmapDrawable(getResources(),Bitmap.createScaledBitmap(bitmap,bitmap.getWidth(),bitmap.getHeight(),true));
}
switch (drawablePosition){
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;
}
}
}
public Bitmap getBitmap(Bitmap bitmap,int width,int height) {
//实际的大小
int totalWidth = bitmap.getWidth();
int totalHeight = bitmap.getHeight();
// int a = width;
// int b = height;
//计算缩放比例
float scaleWidth = (float)width/totalWidth ;
float scaleHeight = (float)height/totalHeight ;
Matrix matrix = new Matrix();
//提交缩放
matrix.postScale(scaleWidth, scaleHeight);
Log.d(TAG, "宽: " + totalWidth + "高:" + totalHeight);
//得到缩放后的图片
Bitmap bitmapResult = Bitmap.createBitmap(bitmap,0,0,totalWidth,totalHeight,matrix,true);
return bitmapResult ;
}
}
大体就是getBitmap()方法是设置drawable的大小以适应我们在xml中设置好的大小,然后调用setCompoundDrawablesWithIntrinsicBounds()这个方法把设置好大小的drawable设置进去就ok了!
最后就是在xml中添加自定义View
<com.hardy.person.myself_view_test.views.DrawableTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="自定义TextView(可以设置嵌入的图片大小,意味着我们再也不用费劲的去用ImageView和TextView组合去显示了)"
android:gravity="center_vertical"
android:drawablePadding="10dp"
app:drawablePosition="bottom"
app:drawableWidth="30dp"
app:drawableHeight="30dp"
app:drawableSrc="@drawable/major"
/>
其中的drawableSrc取代了drawableLeft等属性来设置drawable资源,用drawablePosition来设置图片在文本的哪个方向上,drawableWidth和drawableHeight可以设置图片的大小从而来适应TextView的大小。
No...感觉被坑了,上面说的优点顿时就没了,不能设置成selector的样式,会出现android.graphics.drawable.StateListDrawable cannot be cast to android.graphics.drawable.BitmapDrawable的错误,而且如果在代码中动态改变drawable,只能通过setCompoundDrawablesWithIntrinsicBounds()方法,然后还要像前面说的那样裁剪,EXM?这样一来比组合实现复杂多了好吗!可见这个控件只能适合写死的情况下,而且我觉得写死的情况用它只是少定义两个控件,但是自定义它自己的代码也多了不少好吗!所以我也不见得有什么优点了。。。好失望,如果能设置selector就好了,日后期待自己能完善这个问题。