chenjishi / StateImageButton

A memory reduce image state button

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

StateImageButton

一个旨在减少bitmap内存占用、减少View层级结构的按钮控件。一般来说应用中按钮有很多状态(selected,pressed,disabled, etc),每个状态需要不同的图片去展示,内存中每一种状态的图片都生成一个bitmap对象,从而导致内存升高,很多情况下我们需要保持按钮的显示状态,但是其实不需要设置每种状态的图片资源,因为很多按钮的状态变化其实只是将图片颜色的改变。

StateImageButton通过PorterDuffXfermode.Mode.SRC_IN的方式,在按钮状态变化时染上不同的颜色,从而实现使用一张图片获取不同状态的效果,将原来的多份bitmap内存占用减少到一份。

此外对StateImageButton进行了扩充,使之有了更多的优化特性。

1.减少bitmap资源占用

通常为了实现图片按钮的状态切换,我们需要写一个selector来完成。如果我们想实现按钮的三种状态切换(pressed,disabled,normal),需要三张png图片,如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/star_pressed"/>
    <item android:state_enabled="false" android:drawable="@drawable/star_disabled"/>
    <item android:drawable="@drawable/star_normal"/>
</selector>

star_pressed、star_disabled和star_normal分别代表正常态、按下态和不可点态的图片资源

使用StateImageButton,我们可以仅使用一张图片从而实现三种状态,只需设置正常态的图片资源,按下态和不可点态通过设置颜色实现。

<com.miscell.stateimage.StateImageButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="true"
                state:image_normal="@drawable/star_normal"
                state:color_selected="#3697FE"
                state:color_disabled="#CACACA"/>

color_selected为按下态的颜色,color_disabled为不可点态的颜色。这样star_pressed.png和star_disabled.png就不需要了。

2.减少selector使用

如果图片按钮的每种状态相差很大,无法通过染色实现的话,我们可以采用另一种方法使用StateImageButton。比如,三种状态图片如下

这一种情况我们通过设置StateImageButton的image_normal,image_select和image_disabled属性设置,无需再写selector文件。

<com.miscell.stateimage.StateImageButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="true"
                state:image_normal="@drawable/share_normal"
                state:image_selected="@drawable/share_pressed"
                state:image_disabled="@drawable/share_disabled"/>

3.减少View的嵌套层次及View的数量

如果需要实现一个下图示例的按钮,有图片、文字、小红点,我们需要通过ViewGroup+View嵌套的方式实现。

代码:

 <RelativeLayout
                android:layout_width="58dp"
                android:layout_height="46dp"
                android:clickable="true">
            <ImageView
                    android:id="@+id/image_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/ic_novel"
                    android:layout_centerHorizontal="true"
                    android:layout_marginTop="5dp"/>
            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/image_view"
                    android:layout_centerHorizontal="true"
                    android:text="小说"
                    android:textColor="@android:color/white"
                    android:textSize="11sp"
                    android:layout_marginTop="2dp"/>
            <View android:layout_width="4dp" android:layout_height="4dp"
                  android:background="@drawable/red_dot"
                  android:layout_toRightOf="@id/image_view"
                  android:layout_marginTop="2dp"/>
        </RelativeLayout>

如果使用StateImageButton,则我们只需要一张图片即可,设置图片、文字和小红点的属性如下:

<com.miscell.stateimage.StateImageButton
                android:id="@+id/btn_novel"
                android:layout_width="58dp"
                android:layout_height="46dp"
                android:paddingTop="2dp"
                android:paddingRight="13dp"
                state:text="小说"
                state:state_text_color="@android:color/white"
                state:state_text_size="11sp"
                state:text_image_gap="2dp"
                state:image_height="20dp"
                state:image_width="22dp"
                state:image_normal="@drawable/ic_novel"
                state:image_offset="5dp"
                state:indicator_color="#E14127"
                state:indicator_radius="2.5dp"/>
((StateImageButton) findViewById(R.id.btn_novel)).showIndicator(true);

作为对比我们打开“显示布局边界”查看两种方式实现后View的情况,左边为RelativeLayout实现,右边为StateImageButton实现,可以看出使用StateImageButton实现将原有的4个View减少到了一个。

另外,如果需要点击时有点击状态背景,我们可以给StateImageButton设置属性highlight_color,同样也不需要使用selector。

state:highlight_color="#1AFFFFFF"

4.与Fresco或者Glide配合使用获取网络图片

如果按钮的icon需要从网络获取,比如下图布局

这种情况,需要通过ViewGroup+View组合的方式实现,至少需要3个View(一个RelativeLayout作为容器,一个ImageView显示网络图片,一个TextView显示文字),如果使用StateImageButton只需要一个View即可实现,代码如下:

 <com.miscell.stateimage.StateImageButton android:id="@+id/btn_novel"
                                                 android:layout_width="58dp"
                                                 android:layout_height="46dp"
                                                 state:text="小说"
                                                 state:text_color="#FFF"
                                                 state:text_size="11sp"
                                                 state:text_image_gap="2dp"
                                                 state:image_offset="5dp"/>
String url = "https://dlmse.sogoucdn.com/uploadImage/novel2018@1080_20180103_1514951106.png";
final StateImageButton button = (StateImageButton) findViewById(R.id.btn_novel);
Glide.with(this).load(url).asBitmap().into(new SimpleTarget<Bitmap>() {
    @Override
    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
        if (null != resource) button.setImageBitmap(resource);}
});

具体使用方法请参加项目demo

About

A memory reduce image state button


Languages

Language:Java 100.0%