• Android之缩减apk大小[资源文件篇]:基于自定义Shape设置ShapeDrawable


    过去由于设计湿的吹毛求疵,往往不得不多做很多工作。比如下面的这张图片,很典型的按钮背景图片,一般Android会处理成.9文件以供项目使用。

    button_recharge.png

    但事情往往没有这么简单,需求会要求在不同的地方高度不一致,这个时候.9文件的弱点就出现了。
    我们拿到UI那边的标注以及切图时,会默认高度是不会拉伸或者压缩的,下面截图中右中为期望效果。但是如果我们在应用中使用同一张.9图,就不能确保图片是否会高度拉伸。作为替代方案,只能让UI配合给出N套不同高度的.9文件进行适配。


    上面这种解决方案无形之中增大了安装包的大小,以前见识过使用xml定义shape实现圆角矩形的示例,可以考虑使用代码动态生成Drawable对象,处理好左右两边的圆角弧度即可。

    xml的shape属性对应于ShapeDrawable对象,下面给出ShapeDrawable结合RoundRectShape生成圆角矩形的范例
    int outRadius = 100;
    int innerRadius = 0;
    /*圆角矩形*/
    float[] outerRadii = {outRadius, outRadius, 0, 0, 0, 0, outRadius, outRadius};//左上x2,右上x2,右下x2,左下x2,注意顺序(顺时针依次设置)
    int spaceBetOutAndInner = outRadius - innerRadius;//内外矩形间距
    RectF inset = new RectF(spaceBetOutAndInner, spaceBetOutAndInner, spaceBetOutAndInner, spaceBetOutAndInner);
    float[] innerRadii = {innerRadius, innerRadius, 0, 0, 0, 0, 0, 0};//内矩形 圆角半径
    RoundRectShape roundRectShape = new RoundRectShape(outerRadii, inset, innerRadii);

    ShapeDrawable drawable = new ShapeDrawable(roundRectShape);
    drawable.getPaint().setColor(Color.RED);
    drawable.getPaint().setAntiAlias(true);
    drawable.getPaint().setStyle(Paint.Style.FILL);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    btnActmain.setBackground(drawable);
    } else {
    btnActmain.setBackgroundDrawable(drawable);
    }

    查看RoundRectShape源码可知,其在构造函数中传入内外矩形的圆角半径以及内外矩形间距,因为我们这里的圆角半径需要根据drawable的高度动态修改,查看父类RectShape源码有protect 类型的rect()方法实现,
    /**
    * Returns the RectF that defines this rectangle's bounds.
    */
    protected final RectF rect() {
    return mRect;
    }
    所以修改RoundRectShape的构造函数,将传入参数延迟初始化。

    另观察RectShape得知在onResize中进行mRect的初始化,因此我们选择在调用父类的onResize之后,传入原RoundRectShape构造方法的相关参数。
    @Override
    protected void onResize(float width, float height) {
    mRect.set(0, 0, width, height);
    }

    最后,看看自定义CircleArcRectangleShape类的源码实现,我们让其继承至RectShape,并将RoundRectShape的源码复制过来,主体修改部分如下(其中,clone()方法需要修改一下返回值,这里不予贴出):
    **
    * @Description:
    * @author: Xiaoxuan948
    * @date: 2016/8/23 9:41
    */
    public class CircleArcRectangleShape extends RectShape {
    private final UtilsLog lg = UtilsLog.getLogger(CircleArcRectangleShape.class);
        //修改构造函数
    public CircleArcRectangleShape() {
    mPath = new Path();
    }

    //修改onResize方法
    @Override
    protected void onResize(float w, float h) {
    super.onResize(w, Math.min(w, h));//表示在高大于宽时,默认显示为圆形
    initCircleArcRectangleRadius();//onResize中添加这一句即可

    RectF r = rect();
    mPath.reset();

    if (mOuterRadii != null) {
    mPath.addRoundRect(r, mOuterRadii, Path.Direction.CW);
    } else {
    mPath.addRect(r, Path.Direction.CW);
    }
    if (mInnerRect != null) {
    mInnerRect.set(r.left + mInset.left, r.top + mInset.top,
    r.right - mInset.right, r.bottom - mInset.bottom);
    if (mInnerRect.width() < w && mInnerRect.height() < h) {
    if (mInnerRadii != null) {
    mPath.addRoundRect(mInnerRect, mInnerRadii, Path.Direction.CCW);
    } else {
    mPath.addRect(mInnerRect, Path.Direction.CCW);
    }
    }
    }
    }

    private void initCircleArcRectangleRadius() {
    float outRadius = rect().height();
    float innerRadius = outRadius;//建议设置成与outRadius一致,可防止内外矩形覆盖异常
    float spaceBetOutAndInner = rect().height() / 2 - 1;//内外环的间距,这样设置会使得中间存在一根白线区域
    lg.e("initCircleArcRectangleRadius", outRadius, innerRadius, spaceBetOutAndInner);

    float[] outerRadii = {outRadius, outRadius, outRadius, outRadius, outRadius, outRadius, outRadius, outRadius};//左上x2,右上x2,右下x2,左下x2,注意顺序(顺时针依次设置)
    RectF inset = new RectF(spaceBetOutAndInner, spaceBetOutAndInner, spaceBetOutAndInner, spaceBetOutAndInner);
    float[] innerRadii = {innerRadius, innerRadius, innerRadius, innerRadius, innerRadius, innerRadius, innerRadius, innerRadius};//内矩形圆角半径

    mOuterRadii = outerRadii;
    mInset = inset;
    mInnerRadii = innerRadii;

    if (inset != null) {
    mInnerRect = new RectF();
    }
    }
    }
    以后调用下面的代码,系统将自动根据View的高度生成左右为圆角的按钮背景图片,一套代码完美替换冗余的资源文件。
    ShapeDrawable drawable = new ShapeDrawable(new CircleArcRectangleShape ());






  • 相关阅读:
    【bzoj1196】[HNOI2006]公路修建问题
    【bzoj1082】栅栏[SCOI2005]
    【bzoj1012】[JSOI2008]最大数maxnumber
    【bzoj2330】 [SCOI2011]糖果
    【bzoj1008】[HNOI2008]越狱
    【bzoj1002】 [FJOI2007]轮状病毒DP
    【bzoj1001】[BeiJing2006]狼抓兔子
    C++-POJ2234-Matches Game[Nim][SG函数]
    C++-POJ1067-取石子游戏
    lodash常用
  • 原文地址:https://www.cnblogs.com/linux007/p/5798656.html
Copyright © 2020-2023  润新知