Android图形处理-Drawabble
Drawable
drawable是一个抽象类,本质就是图形和动画。
两种访问模式
- 通过@deawable/name在xml中引用
- 通过.drawable.name在java代码中使用
第二种使用方式的本质就是一个int
子类
主要的子类有:LayerDrawavle、ShapeDrawable、NinePathDrawable、StateListDrawable、ClipDrawable、AnimationDrawable。
LayerDrawavle
就是层的Drawable,新增的item会盖住原来的item所代表的图像,对应xml的标签是layer-list,
android:drawable表示对应的drawable就是图形或者动画
android:top|bottom|left|right表示图形在组件的位置
自定义SeekBar
两个关键属性:
android:progressDrawable指定背景
android:thumb指定滑块
其中progressDrawable要指定两个Android官方的属性,分别制定划过的Drawable和没有划过的Drawable:
SeekBar的背景
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@android:id/background"
android:drawable="@drawable/background"/>
<item
android:id="@android:id/progress"
android:drawable="@drawable/progress"/>
</layer-list>
@android:id/background官方指定的没有滑动的背景
@android:id/progress已经划过的颜色
SeekBar的代码
<SeekBar android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progressDrawable="@drawable/layer"
android:thumb="@drawable/thumb"/>
主要是滑块的属性:android:thumb
ShapeDrawable
在xml中对应的shape属性
实例
代码
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!--size表示这个shape的大小-->
<size android:width="100dp" android:height="10dp"/>
<!--solid表示这个形状怎么填充,其中只有一个color属性-->
<solid android:color="@color/colorAccent"/>
<!--stroke边框-->
<stroke android:width="1dp" android:color="@color/colorPrimary"/>
<!--gradient颜色渐变,默认的type是linear-->
<gradient android:centerColor="@color/colorAccent"
android:endColor="@color/colorPrimaryDark"
android:startColor="@color/colorPrimary"
android:type="linear"/>
<!--padding图形的内边距-->
<padding android:bottom="4dp"/>
<!--corners处理图形的边角-->
<corners android:radius="3dp"/>
</shape>
StateListDrawable
对应xml中的selector
TextView自定义颜色
当EditText获得焦点的时候,字体颜色发生变化
代码
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/colorAccent" android:state_focused="true"/>
<item android:color="@color/colorPrimary" android:state_focused="false"/>
</selector>
就是颜色和状态的结合
EditText的实现:
<EditText android:layout_width="match_parent" android:layout_height="wrap_content"
android:text="你好"
android:textColor="@drawable/color"/>
就是textColor属性指定Drawable
ClipDrawable
在xml中对应的clip标签
bug说明
在使用图片的时候一定要注意格式,出现这个错误就是图片的格式异常,在win直接改后缀名图片正常显示,但是在Andorid不能正常显示
出现错误的图片根本不能编译,无论图片是否正在使用
不断展开的画卷
这就是不断的改变ClipDrawable的剪切位置来实现
ClipDrawable的实现
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="horizontal"
android:drawable="@drawable/good"
android:gravity="center">
</clip>
android:clipOrientation裁剪的方向
android:drawable裁剪的图片
android:gravity对其的方向
不断改变裁剪的Level
// 把ImageView的src抽取成一个Drawable
private Drawable mDrawable;
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0) {
// 不断改变level
mDrawable.setLevel(mDrawable.getLevel() + 100);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
// initAnim();
}
private void init() {
ImageView imageView = (ImageView) findViewById(R.id.iv);
mDrawable = imageView.getDrawable();
new Timer().schedule(new TimerTask() {
@Override
public void run() {
Message message = new Message();
message.what = 0;
mHandler.sendMessage(message);
if (mDrawable.getLevel() >= 10000) {
cancel();
}
}
// 设置周期是100毫秒
}, 0, 100);
}
注意可以实现周期的类Timer
Bitmap和BitmapDrawable
BItmapDrawable内部封装的就是一个Bitmap,也可以从Drawable中拿到Bitmap
一个Bitmap就是一张位图,而BitmapDrawable就是它的封装类,封装方法:
BitmapDrawable(Resources res, Bitmap bitmap)
第一个参数就是: getApplicationContext().getResources()
可以调用BitmapDrawable中的getBitmap,反过来也可以:
Bitmap getBitmap ()
public class BitmapDrawable extends Drawable
还有一个重要的类就是BitmapFractory负责产生Bitmap:
就是几乎可以从各种资源加载并且装换成Bitmap
回收
BItmap加载显示大量耗费资源所以及时判断是否回收,BItmap有isRecycled和recycled两个方法分别判断是否回收和主动回收:
简单案例
就是两个button然后在assets目录中查找并且显示图片,借鉴自疯狂android:
- 获取assets中的资源,并且存储在数组中
private void init() {
mAssetManager = getAssets();
try {
mList = mAssetManager.list("");
} catch (IOException e) {
e.printStackTrace();
}
}
- 添加事件监听
@OnClick({R.id.button2, R.id.button})
public void onClick(View view) {
switch (view.getId()) {
case R.id.button2:
- 实现具体的逻辑
这里的思路很好玩,主要是应该用一个指针来指明哪个是正在显示的图片,然后在最开始就应该判断是否越界,这时候重点来了,通过文件名的后缀可以得到资源的类型(while),注意条件是反的,而且还应该判断是否越界:
if (currentPicture >= mList.length) {
currentPicture = 0;
}
while (!mList[currentPicture].endsWith(".jpg")) {
currentPicture++;
if (currentPicture >= mList.length) {
currentPicture = 0;
}
}
ImageView可以得到它的Dradable
BitmapDrawable drawable = (BitmapDrawable) mImageView.getDrawable();
AssetsManager打开资源:
mAssetManager.open(mList[currentPicture++]))
全部代码
@BindView(R.id.button2)
Button mButton2;
@BindView(R.id.button)
Button mButton;
@BindView(R.id.imageView)
ImageView mImageView;
private String[] mList;
private AssetManager mAssetManager;
private int currentPicture = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
init();
}
private void init() {
mAssetManager = getAssets();
try {
mList = mAssetManager.list("");
} catch (IOException e) {
e.printStackTrace();
}
}
@OnClick({R.id.button2, R.id.button})
public void onClick(View view) {
switch (view.getId()) {
case R.id.button2:
if (currentPicture >= mList.length) {
currentPicture = 0;
}
while (!mList[currentPicture].endsWith(".jpg")) {
currentPicture++;
//注意这里要第二次判断是否越界的问题
if (currentPicture >= mList.length) {
currentPicture = 0;
}
}
BitmapDrawable drawable = (BitmapDrawable) mImageView.getDrawable();
if (drawable != null && !drawable.getBitmap().isRecycled()) {
drawable.getBitmap().recycle();
}
try {
mImageView.setImageBitmap(BitmapFactory.decodeStream(mAssetManager.open(mList[currentPicture++])));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("---------------");
break;
case R.id.button:
System.out.println("-------111111111111--------");
break;
}
}