**Lroid是一款基于Anddroid平台开发的app, 是一款旨在提高刚想要入行Android系统开发(但已经具备Java语言基础)或者已经开始工作一段时间(但已经具备Java语言基础)想要进一步提高自己能力的app。lroid是以当下流行的MVP为架构,网络通信模块采用retrofit 2.0。里面还包括了RxJava,Dagger2等很热门的应用框架。为了更加接近现实常用的app,而不是一味的讲解Android开发知识点,本软件整合了一些内容来填充框架。
https://item.taobao.com/item.htm?id=541493148052**
在Android中有这样一个类它有点像Bitmap,但却和Bitmap有着本质的区别,那就是——Drawable。我们先来看一下官方文档对它的描述吧。
A Drawable is a general abstraction for “something that can be drawn.”
Most often you will deal with Drawable as the type of resource
retrieved for drawing things to the screen; the Drawable class
provides a generic API for dealing with an underlying visual resource
that may take a variety of forms. Unlike a {@link android.view.View},
a Drawable does not have any facility to receive events or otherwise
interact with the user.
大体意思就是,可以用来画一些东东的东西。
好,让我们看看今天主要学习它哪些地方吧:
- Drawable和Bitmap的区别以及两者的互相转换。
- Drawable的基本用法。
- Drawable的高级用法。
一、Drawable和Bitmap的区别以及两者的互相转换。
Bitmap大家应该都挺熟悉的,描述的是位图,用于图的处理。
我们先来看看Bitmap如何转换成Drawable,这个转换还是比较简单的,Google给我们提供了一个很方便的类——BitmapDrawable。我们只需将一个Bitmap封装到BitmapDrawable就可以得到Drawable对象,具体代码:
public Drawable bitmapToDrawable(Bitmap bitmap){
Drawable drawable = new BitmapDrawable(getResources(),bitmap);
return drawable;
}
下面看看如何将一个Drawable对象转换成Bitmap对象,这个有点复杂,具体代码如下:
public Bitmap drawableToBitmap(Drawable drawable){
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(width,height,drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0,0,width,height);
drawable.draw(canvas);
return bitmap;
}
代码其实还是挺好理解的,创建一个画布,通过Drawable的draw()方法,把图像信息封装到Bitmap中,就可以得到Bitmap对象。
然后就可以通过ImageView的setImageBitmap(Bitmap bitmap)方法和setImageDrawable(Drawable drawable)方法来展示图片。
好,明白了Drawable和Bitmap的关系,下面让我来看看Drawable的基本用法。
二、Drawable的基本用法。
先来看一张图:
是不是有很多我们经常通过XML用到的标签。是的,每一个标签都对应了一个Drawable类,以我们最常用的Shape来说,通过XML我们会这样书写:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="8dp"
android:bottomRightRadius="8dp"
android:topLeftRadius="8dp"
android:topRightRadius="8dp" />
<stroke
android:width="1dp"
android:color="#f00" />
<solid android:color="#f00"/>
</shape>
效果如下:
好,我们通过代码来实现上述效果:
注:标签Shape对于的Java类不是ShapeDrawable,而是GradientDrawable类,千万不要搞错了
GradientDrawable gradientDrawable = new GradientDrawable();
gradientDrawable.setCornerRadius(8.0f);
gradientDrawable.setColor(Color.RED);
gradientDrawable.setStroke(1,Color.RED);
效果和上面是一样的,是不是觉得用代码控制更简单呢,短短几行代码,就可以实现相同的效果。
好,其他的Drawable类型,大家可以自己亲自动手尝试用代码如何现实XML现实的效果,我就不一一在这介绍了。
下面我们来看一个比较综合的效果,也是开发中一个常见的效果,在iOS比较常见,效果图如下:
仿照QQ首页顶部栏。
先来说一下我们的实现思路,方案还是有很多种的:
1,RadioGroup+RadioButton的方式
2,普通布局(LinearLayout或者RelativeLayout)+Button的方式
在这里我们用第一方案,原因是第二中方法我们得自己判断互斥逻辑,比较麻烦,通过第一中方案,就可以直接使用系统已经实现好的逻辑。我们只需要关心的就是如何改变背景而已。
好,具体布局如下:
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_marginTop="10dp"
android:padding="10dp"
android:background="#990000ff"
android:orientation="horizontal">
<RadioButton
android:id="@+id/id_left_radio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:button="@null"
android:background="@drawable/left_radio_bg"
android:textColor="#f00"
android:padding="8dp"
android:text="消息"/>
<RadioButton
android:id="@+id/id_right_radio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:button="@null"
android:background="@drawable/right_radio_bg"
android:textColor="#f00"
android:padding="8dp"
android:text="语音"/>
</RadioGroup>
左边RadioButton的背景实现如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@drawable/left_checked_bg"></item>
<item android:state_checked="false" android:drawable="@drawable/left_unchecked_bg"></item>
</selector>
checked状态背景:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:topLeftRadius="5dp" android:bottomLeftRadius="5dp"></corners>
<solid android:color="#fff"></solid>
<stroke android:width="1dp" android:color="#fff"></stroke>
</shape>
unchecked状态背景如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:topLeftRadius="5dp" android:bottomLeftRadius="5dp"></corners>
<solid android:color="@android:color/transparent"></solid>
<stroke android:width="1dp" android:color="#fff"></stroke>
</shape>
右边的就不具体把代码贴出来了,就是left换成right而已。
这样我们就实现了上图的效果,效果还是挺赞的。是不是很简单呢,嘿嘿,我们来看看用代码如何实现这样的效果。
还是左边效果:
StateListDrawable stateListDrawable = new StateListDrawable();
GradientDrawable checkedDrawable = new GradientDrawable();
checkedDrawable.setColor(Color.WHITE);
checkedDrawable.setStroke(2,Color.WHITE);
checkedDrawable.setCornerRadii(new float[]{
//1、2表示左上角,3、4表示右上角,5、6表示右下角,7、8表示左下角
8.0f,
8.0f,
0.0f,
0.0f,
0.0f,
0.0f,
8.0f,
8.0f
});
stateListDrawable.addState(new int[]{android.R.attr.state_checked},checkedDrawable);
GradientDrawable unCheckedDrawable = new GradientDrawable();
unCheckedDrawable.setColor(Color.TRANSPARENT);
unCheckedDrawable.setStroke(2,Color.WHITE);
unCheckedDrawable.setCornerRadii(new float[]{
//1、2表示左上角,3、4表示右上角,5、6表示右下角,7、8表示左下角
8.0f,
8.0f,
0.0f,
0.0f,
0.0f,
0.0f,
8.0f,
8.0f
});
stateListDrawable.addState(new int[]{ - android.R.attr.state_checked },unCheckedDrawable);
这样我们也就实现了XML实现的效果。需要注意几点:
1,setCornerRadii()方法中各个参数代表的含义。代码中已经标明。
2,checked状态和unchecked状态如何用代码实现。
至此,我们这个小例子就通过两种不同的方式实现了,在实际开发中,你可以根据个人喜好自由选择,各有利弊,我喜好代码~
下面我们再来看一个小例子,也是开发中比较常用的,就是数量指示器,效果如下:
一般我们看着这样的效果都会找美工要一个背景图,或者自己自定义一个View来实现这样的效果,下面我们就通过Drawable来看看如何实现这样的效果,同样,我们先来看一下通过XML如何实现具体代码如下:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#f00" />
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<solid android:color="#f00" />
<stroke
android:width="1dp"
android:color="@android:color/white" />
<size
android:width="15dp"
android:height="15dp" />
</shape>
需要注意几点:
1、android:shape=”oval”属性值,默认为rectangle。
2、size标签
其他的都是平常用的,没什么好说的,再来看一下通过代码如何实现:
GradientDrawable gradientDrawable = new GradientDrawable();
gradientDrawable.setShape(GradientDrawable.OVAL);
gradientDrawable.setStroke(2,Color.WHITE);
gradientDrawable.setColor(Color.RED);
gradientDrawable.setSize(30,30);
效果和XML一样。
三、 Drawable的高级用法。
接触过Android开发的人,都知道我们可以自定义一个View来实现一些特效,那么我们可不可以自定义一个Drawable呢,答案当然是可以的,下面我们来看看如何自定义一个Drawable。还是以实例为主我们来实现一个圆形图片,要想实现圆形图片方法有几种一般都是自定义ImageView重写onDraw,其实用Drawable也可以的。先看效果图:
代码:
public class CircleDrawable extends Drawable {
private Paint mPaint;
private int mRadius;
public CircleDrawable(Bitmap bitmap){
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint.setShader(shader);
mRadius = Math.min(bitmap.getWidth(),bitmap.getHeight()) /2;
}
@Override
public int getIntrinsicHeight() {
return mRadius * 2 ;
}
@Override
public int getIntrinsicWidth() {
return mRadius * 2;
}
@Override
public void draw(Canvas canvas) {
canvas.drawCircle(mRadius,mRadius,mRadius,mPaint);
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
mPaint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return PixelFormat.RGB_888;
}
}
好,对于Drawable的高级用法就先介绍这一个,还有一些常用的,等以后再慢慢介绍。主要是基本用法,希望大家都能掌握了,今后用到了可以运用自如。