Android Drawable 那些不为人知的高效用法

看下用法:

Bitmap bitmap = BitmapFactory.decodeResource(getResources(),

R.drawable.mv);

ImageView iv = (ImageView) findViewById(R.id.id_one);

iv.setImageDrawable(new RoundImageDrawable(bitmap));

ok,贴一下我们的效果图,两个ImageView和一个TextView

可以看到,不仅仅用于ImageView去实现圆角图片,并且可以作为任何View的背景,在ImageView中的拉伸的情况,配下ScaleType即可。在其他View作为背景时,如果出现拉伸情况,请参考:Android BitmapShader 实战 实现圆形、圆角图片 。 足够详细了。

2、CircleImageDrawable


那么下来,我们再看看自定义圆形Drawable的写法:

package com.zhy.view;

import android.graphics.Bitmap;

import android.graphics.BitmapShader;

import android.graphics.Canvas;

import android.graphics.ColorFilter;

import android.graphics.Paint;

import android.graphics.PixelFormat;

import android.graphics.RectF;

import android.graphics.Shader.TileMode;

import android.graphics.drawable.Drawable;

public class CircleImageDrawable extends Drawable

{

private Paint mPaint;

private int mWidth;

private Bitmap mBitmap ;

public CircleImageDrawable(Bitmap bitmap)

{

mBitmap = bitmap ;

BitmapShader bitmapShader = new BitmapShader(bitmap, TileMode.CLAMP,

TileMode.CLAMP);

mPaint = new Paint();

mPaint.setAntiAlias(true);

mPaint.setShader(bitmapShader);

mWidth = Math.min(mBitmap.getWidth(), mBitmap.getHeight());

}

@Override

public void draw(Canvas canvas)

{

canvas.drawCircle(mWidth / 2, mWidth / 2, mWidth / 2, mPaint);

}

@Override

public int getIntrinsicWidth()

{

return mWidth;

}

@Override

public int getIntrinsicHeight()

{

return mWidth;

}

@Override

public void setAlpha(int alpha)

{

mPaint.setAlpha(alpha);

}

@Override

public void setColorFilter(ColorFilter cf)

{

mPaint.setColorFilter(cf);

}

@Override

public int getOpacity()

{

return PixelFormat.TRANSLUCENT;

}

}

一样出奇的简单,再看一眼效果图:

ok,关于自定义Drawable的例子over~~~接下来看自定义状态的。

上述参考了:Romain Guy’s Blog

3、自定义Drawable State

===================

关于Drawable State,state_pressed神马的,相信大家都掌握的特别熟练了。

那么接下来,我们有个需求,类似于邮箱,邮件以ListView形式展示,但是我们需要一个状态去标识出未读和已读:so,我们自定义一个状态state_message_readed。

效果图:

可以看到,如果是已读的邮件,我们的图标是打开状态,且有个淡红色的背景。那么如何通过自定义drawable state 实现呢?

自定义drawable state 需要分为以下几个步骤:

1、res/values/新建一个xml文件:drawable_status.xml

<?xml version="1.0" encoding="utf-8"?>

2、继承Item的容器

我们这里Item选择RelativeLayout实现,我们需要继承它,然后复写它的onCreateDrawableState方法,把我们自定义的状态在合适的时候添加进去。

package com.zhy.view;

import com.zhy.sample.drawable.R;

import android.content.Context;

import android.util.AttributeSet;

import android.widget.RelativeLayout;

public class MessageListItem extends RelativeLayout

{

private static final int[] STATE_MESSAGE_READED = { R.attr.state_message_readed };

private boolean mMessgeReaded = false;

public MessageListItem(Context context, AttributeSet attrs)

{

super(context, attrs);

}

public void setMessageReaded(boolean readed)

{

if (this.mMessgeReaded != readed)

{

mMessgeReaded = readed;

refreshDrawableState();

}

}

@Override

protected int[] onCreateDrawableState(int extraSpace)

{

if (mMessgeReaded)

{

final int[] drawableState = super

.onCreateDrawableState(extraSpace + 1);

mergeDrawableStates(drawableState, STATE_MESSAGE_READED);

return drawableState;

}

return super.onCreateDrawableState(extraSpace);

}

}

代码不复杂,声明了一个STATE_MESSAGE_READED,然后在mMessgeReaded=true的情况下,通过onCreateDrawableState方法,加入我们自定义的状态。

类似的代码,大家可以看看CompoundButton(CheckBox父类)的源码,它有个checked状态:

@Override

protected int[] onCreateDrawableState(int extraSpace) {

final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);

if (isChecked()) {

mergeDrawableStates(drawableState, CHECKED_STATE_SET);

}

return drawableState;

}

3、使用

布局文件:

<com.zhy.view.MessageListItem xmlns:android=“http://schemas.android.com/apk/res/android”

xmlns:tools=“http://schemas.android.com/tools”

android:layout_width=“match_parent”

android:layout_height=“50dp”

android:background=“@drawable/message_item_bg” >

<ImageView

android:id=“@+id/id_msg_item_icon”

android:layout_width=“30dp”

android:src=“@drawable/message_item_icon_bg”

android:layout_height=“wrap_content”

android:duplicateParentState=“true”

android:layout_alignParentLeft=“true”

android:layout_centerVertical=“true”

/>

<TextView

android:id=“@+id/id_msg_item_text”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:layout_centerVertical=“true”

android:layout_toRightOf=“@id/id_msg_item_icon” />

</com.zhy.view.MessageListItem>

很简单,一个图标,一个文本;

Activity

package com.zhy.sample.drawable;

import com.zhy.view.MessageListItem;

import android.app.ListActivity;

import android.os.Bundle;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ArrayAdapter;

import android.widget.TextView;

public class CustomStateActivity extends ListActivity

{

private Message[] messages = new Message[] {

new Message(“Gas bill overdue”, true),

new Message(“Congratulations, you’ve won!”, true),

new Message(“I love you!”, false),

new Message(“Please reply!”, false),

new Message(“You ignoring me?”, false),

new Message(“Not heard from you”, false),

new Message(“Electricity bill”, true),

new Message(“Gas bill”, true), new Message(“Holiday plans”, false),

new Message(“Marketing stuff”, false), };

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

getListView().setAdapter(new ArrayAdapter(this, -1, messages)

{

private LayoutInflater mInflater = LayoutInflater

.from(getContext());

@Override

public View getView(int position, View convertView, ViewGroup parent)

{

if (convertView == null)

{

convertView = mInflater.inflate(R.layout.item_msg_list,

parent, false);

}

MessageListItem messageListItem = (MessageListItem) convertView;

TextView tv = (TextView) convertView

.findViewById(R.id.id_msg_item_text);

tv.setText(getItem(position).message);

messageListItem.setMessageReaded(getItem(position).readed);

return convertView;

}

});

}

}

代码很简单,但是可以看到,我们需要在getView里面中去使用调用setMessageReaded方法,当然了其他的一些状态,肯定也要手动触发,比如在ACTION_DOWN中触发pressed等。请勿纠结咋没有使用ViewHolder什么的,自己添加下就行。

本例参考自:Example from github

4、提升我们的UI Perfermance

======================

现在大家越来越注重性能问题,其实没必要那么在乎,但是既然大家在乎了,这里通过Cyril Mottier :master_android_drawables ppt中的一个例子来说明如果利用Drawable来提升我们的UI的性能。

大家看这样一个效果图:

布局文件:

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android=“http://schemas.android.com/apk/res/android”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

android:background=“@color/app_background”

android:padding=“8dp” >

<ImageView

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_gravity=“center”

android:layout_marginBottom=“24dp”

android:src=“@drawable/logo” />

<LinearLayout

android:layout_width=“match_parent”

最后

感觉现在好多人都在说什么安卓快凉了,工作越来越难找了。又是说什么程序员中年危机啥的,为啥我这年近30的老农根本没有这种感觉,反倒觉得那些贩卖焦虑的都是瞎j8扯谈。当然,职业危机意识确实是要有的,但根本没到那种草木皆兵的地步好吗?

Android凉了都是弱者的借口和说辞。虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。

所以,最后这里放上我耗时两个月,将自己8年Android开发的知识笔记整理成的Android开发者必知必会系统学习资料笔记,上述知识点在笔记中都有详细的解读,里面还包含了腾讯、字节跳动、阿里、百度2019-2021面试真题解析,并且把每个技术点整理成了视频和PDF(知识脉络 + 诸多细节)。

以上全套学习笔记面试宝典,吃透一半保你可以吊打面试官,只有自己真正强大了,有核心竞争力,你才有拒绝offer的权力,所以,奋斗吧!骚年们!千里之行,始于足下。种下一颗树最好的时间是十年前,其次,就是现在。

最后,赠与大家一句诗,共勉!

不驰于空想,不骛于虚声。不忘初心,方得始终。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。

所以,最后这里放上我耗时两个月,将自己8年Android开发的知识笔记整理成的Android开发者必知必会系统学习资料笔记,上述知识点在笔记中都有详细的解读,里面还包含了腾讯、字节跳动、阿里、百度2019-2021面试真题解析,并且把每个技术点整理成了视频和PDF(知识脉络 + 诸多细节)。

[外链图片转存中…(img-H5mytR90-1714124628525)]

以上全套学习笔记面试宝典,吃透一半保你可以吊打面试官,只有自己真正强大了,有核心竞争力,你才有拒绝offer的权力,所以,奋斗吧!骚年们!千里之行,始于足下。种下一颗树最好的时间是十年前,其次,就是现在。

最后,赠与大家一句诗,共勉!

不驰于空想,不骛于虚声。不忘初心,方得始终。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值