**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(,,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(f);
gradientDrawable.setColor(Color.RED);
gradientDrawable.setStroke(,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(,Color.WHITE);
checkedDrawable.setCornerRadii(new float[]{
//1、2表示左上角,3、4表示右上角,5、6表示右下角,7、8表示左下角
,
,
,
,
,
,
,
});
stateListDrawable.addState(new int[]{android.R.attr.state_checked},checkedDrawable);
GradientDrawable unCheckedDrawable = new GradientDrawable();
unCheckedDrawable.setColor(Color.TRANSPARENT);
unCheckedDrawable.setStroke(,Color.WHITE);
unCheckedDrawable.setCornerRadii(new float[]{
//1、2表示左上角,3、4表示右上角,5、6表示右下角,7、8表示左下角
,
,
,
,
,
,
,
});
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(,Color.WHITE);
gradientDrawable.setColor(Color.RED);
gradientDrawable.setSize(,);
效果和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()) /;
}
@Override
public int getIntrinsicHeight() {
return mRadius * ;
}
@Override
public int getIntrinsicWidth() {
return mRadius * ;
}
@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的進階用法就先介紹這一個,還有一些常用的,等以後再慢慢介紹。主要是基本用法,希望大家都能掌握了,今後用到了可以運用自如。