ClipDrawable让开发更简单

用ClipDrawable实现音频录制是的麦克风分贝效果 用ClipDrawable实现一个音频录制时麦克风随着说话分贝的大小的一个动效!! 阅读详情

ClipDrawable让开发更简单

Android开发者对Drawable自然是无比熟悉,Drawable代表一类可以绘制的东西,它有许多继承类,常见的就是BitmapDrawable,此外ShapeDrawable,LayerListDrawable也用得比较多,这篇文章讲另外一个比较常见的类ClipDrawable。ClipDrawable非常简单,写博客是因为觉得它非常好用,有时候合理的运用能让代码编写过程中非常愉悦

ClipDrawable是Drawable中的一种,和我们常见的BitmapDrawable是同类。主要功能是能针对自身进行裁剪复制显示。

先看看效果图。
这里写图片描述

文章开头有说过Drawable,Drawable只是一个抽象类,它有许多子类,常见的有bitmapdrawable、LayerDrawable、LevelListDrawable和ClipDrawable等等。
大家可以看下它的源码。(代码有删简)

public abstract class Drawable {


    /**
     * Draw in its bounds (set via setBounds) respecting optional effects such
     * as alpha (set via setAlpha) and color filter (set via setColorFilter).
     *
     * @param canvas The canvas to draw into
     */
    public abstract void draw(Canvas canvas);


    /**
     * Create a drawable from inside an XML document using an optional
     * {@link Theme}. Called on a parser positioned at a tag in an XML
     * document, tries to create a Drawable from that tag. Returns {@code null}
     * if the tag is not a valid drawable.
     */
    public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs,
            Theme theme) throws XmlPullParserException, IOException {
        final Drawable drawable;

        final String name = parser.getName();
        if (name.equals("selector")) {
            drawable = new StateListDrawable();
        } else if (name.equals("animated-selector")) {
            drawable = new AnimatedStateListDrawable();
        } else if (name.equals("level-list")) {
            drawable = new LevelListDrawable();
        } else if (name.equals("layer-list")) {
            drawable = new LayerDrawable();
        } else if (name.equals("transition")) {
            drawable = new TransitionDrawable();
        } else if (name.equals("ripple")) {
            drawable = new RippleDrawable();
        } else if (name.equals("color")) {
            drawable = new ColorDrawable();
        } else if (name.equals("shape")) {
            drawable = new GradientDrawable();
        } else if (name.equals("vector")) {
            drawable = new VectorDrawable();
        } else if (name.equals("animated-vector")) {
            drawable = new AnimatedVectorDrawable();
        } else if (name.equals("scale")) {
            drawable = new ScaleDrawable();
        } else if (name.equals("clip")) {
            drawable = new ClipDrawable();
        } else if (name.equals("rotate")) {
            drawable = new RotateDrawable();
        } else if (name.equals("animated-rotate")) {
            drawable = new AnimatedRotateDrawable();
        } else if (name.equals("animation-list")) {
            drawable = new AnimationDrawable();
        } else if (name.equals("inset")) {
            drawable = new InsetDrawable();
        } else if (name.equals("bitmap")) {
            //noinspection deprecation
            drawable = new BitmapDrawable(r);
            if (r != null) {
               ((BitmapDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
            }
        } else if (name.equals("nine-patch")) {
            drawable = new NinePatchDrawable();
            if (r != null) {
                ((NinePatchDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
             }
        } else {
            throw new XmlPullParserException(parser.getPositionDescription() +
                    ": invalid drawable tag " + name);
        }

        drawable.inflate(r, parser, attrs, theme);
        return drawable;
    }


}
  • 1

在上面的
createFromXmlInner()
方法中可以看到通过解析xml中的各种标签会创建相应的子类。今天我们的主题就是它的子类之一–ClipDrawable。

用法

ClipDrawable用法非常简单,ClipDrawable可以在xml文件配置,比如我在工程的res/drawable下创建一个文件 test_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/test"/>
</clip>
  • 1

然后在activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.frank.clipdrawabledemo.MainActivity">

    <TextView
        android:id="@+id/tv_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <ImageView
        android:id="@+id/iv_show"
        android:layout_below="@id/tv_info"
        android:layout_width="match_parent"
        android:layout_height="500dp"
        android:background="@drawable/test_drawable"
        />
    <SeekBar
        android:id="@+id/seekbar"
        android:layout_below="@id/iv_show"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</RelativeLayout>
  • 1

把ClipDrawable资源设置作为ImageView的background

然后在代码中

mSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        int max = seekBar.getMax();
        double scale = (double)progress/(double)max;
        ClipDrawable drawable = (ClipDrawable) mImageShow.getBackground();
        drawable.setLevel((int) (10000*scale));
        mTvShow.setText(progress+"");
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }
});
  • 1

我们通过一个SeekBar来控制ClipDrawable的level,调用的是它的setLevel()方法。最终可以让它显示不同的比例。 效果就是前面的图像效果。

在ClipsDrawable中level取值从0~10000.其中0表示ClipDrawable完全不能显示,10000表示完全显示,而这之间的值对应着不同的比例。
ClipDrawable还可以在xml中布置它的方向,和它画面增长的位置。

方向

android:clipOrientation="vertical|horizontal"
android:gravity="left|right|top|bottom|center"
  • 1

clipOrientation是指图像复制的方向是水平还是垂直。
ClipDrawable中默认的方向是horizontal,说明显示内容的增长是自横向的。当设置为vertical时,表明显示内容的增长是竖向的。
当然clipOrientation是和Gravity配合使用的。ClipDrawable中默认的clipOrientation是horizontal,而默认的gravity是left。
gravity可以看作是起点的位置,比如默认的left的话,表明水平方向,图像复制是从左边增长到右边。

接下来我们看具体的场景

右—->左

我们也可以让内容从右边向左边增长,只需要如下配置

<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/test"
    android:clipOrientation="horizontal"
    android:gravity="right">
</clip>
  • 1

效果如下:
这里写图片描述

从中间向两边:

水平方向

<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/test"
    android:clipOrientation="horizontal"
    android:gravity="center">
</clip>
  • 1

这里写图片描述

还有这样,垂直方向

<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/test"
    android:clipOrientation="vertical"
    android:gravity="center">
</clip>
  • 1

这里写图片描述

从上到下:

<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/test"
    android:clipOrientation="vertical"
    android:gravity="top">
</clip>
  • 1

这里写图片描述

从下到上:

<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/test"
    android:clipOrientation="vertical"
    android:gravity="top">
</clip>
  • 1

这里写图片描述

注意点

clipOrientation为horizontal时,gravity为top或者bottom时,会被处理为gravity为center.
clipOritentation为vertical时,gravity为left或者right时,也会处理为gravity为center.

ClipDrawable的秘密和原理

掌握上面的方法,我们就可以愉快地玩耍了,可以应付很多场景了,比如系统的ProgressBar其实就运用了ClipDrawable作进度条的图像,进行水平方向的裁剪复制。但是,作为开发者而言,还可以稍微深入了解一下它的源码。

其实我看见ClipDrawable就在想它是怎么实现图像的裁剪的。那好,看源代码吧。

public class ClipDrawable extends Drawable implements Drawable.Callback {
    private ClipState mClipState;
    private final Rect mTmpRect = new Rect();

    public static final int HORIZONTAL = 1;
    public static final int VERTICAL = 2;

    ClipDrawable() {
        this(null, null);
    }

    /**
     * @param orientation Bitwise-or of {@link #HORIZONTAL} and/or {@link #VERTICAL}
     */
    public ClipDrawable(Drawable drawable, int gravity, int orientation) {
        this(null, null);
        //ClipDrawable包裹其它的Drawable
        mClipState.mDrawable = drawable;
        mClipState.mGravity = gravity;
        mClipState.mOrientation = orientation;

        if (drawable != null) {
            drawable.setCallback(this);
        }
    }

    @Override
    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
            throws XmlPullParserException, IOException {
        super.inflate(r, parser, attrs, theme);

        int type;

        TypedArray a = obtainAttributes(
                r, theme, attrs, com.android.internal.R.styleable.ClipDrawable);

        int orientation = a.getInt(
                com.android.internal.R.styleable.ClipDrawable_clipOrientation,
                HORIZONTAL);
        int g = a.getInt(com.android.internal.R.styleable.ClipDrawable_gravity, Gravity.LEFT);
        Drawable dr = a.getDrawable(com.android.internal.R.styleable.ClipDrawable_drawable);

        a.recycle();

        final int outerDepth = parser.getDepth();
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
            if (type != XmlPullParser.START_TAG) {
                continue;
            }
            dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
        }

        if (dr == null) {
            throw new IllegalArgumentException("No drawable specified for <clip>");
        }

        mClipState.mDrawable = dr;
        mClipState.mOrientation = orientation;
        mClipState.mGravity = g;

        dr.setCallback(this);
    }

    ......



    @Override
    protected boolean onLevelChange(int level) {
        mClipState.mDrawable.setLevel(level);
        invalidateSelf();
        return true;
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        mClipState.mDrawable.setBounds(bounds);
    }

    @Override
    public void draw(Canvas canvas) {

        if (mClipState.mDrawable.getLevel() == 0) {
            return;
        }

        final Rect r = mTmpRect;
        final Rect bounds = getBounds();
        int level = getLevel();
        int w = bounds.width();
        final int iw = 0; //mClipState.mDrawable.getIntrinsicWidth();
        if ((mClipState.mOrientation & HORIZONTAL) != 0) {
            w -= (w - iw) * (10000 - level) / 10000;
        }
        int h = bounds.height();
        final int ih = 0; //mClipState.mDrawable.getIntrinsicHeight();
        if ((mClipState.mOrientation & VERTICAL) != 0) {
            h -= (h - ih) * (10000 - level) / 10000;
        }
        final int layoutDirection = getLayoutDirection();
        Gravity.apply(mClipState.mGravity, w, h, bounds, r, layoutDirection);

        if (w > 0 && h > 0) {
            canvas.save();
            canvas.clipRect(r);
            mClipState.mDrawable.draw(canvas);
            canvas.restore();
        }
    }



    final static class ClipState extends ConstantState {
        Drawable mDrawable;
        int mChangingConfigurations;
        int mOrientation;
        int mGravity;


        ClipState(ClipState orig, ClipDrawable owner, Resources res) {
            if (orig != null) {
                if (res != null) {
                    mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
                } else {
                    mDrawable = orig.mDrawable.getConstantState().newDrawable();
                }
                mDrawable.setCallback(owner);
                mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
                mDrawable.setBounds(orig.mDrawable.getBounds());
                mDrawable.setLevel(orig.mDrawable.getLevel());
                mOrientation = orig.mOrientation;
                mGravity = orig.mGravity;
                mCheckedConstantState = mCanConstantState = true;
            }
        }

        @Override
        public Drawable newDrawable() {
            return new ClipDrawable(this, null);
        }

        @Override
        public Drawable newDrawable(Resources res) {
            return new ClipDrawable(this, res);
        }

        .....
    }

    ......
}
  • 1

源码没有多少,我删简了一些。保留了主体信息。从源码中我们可以得到下面的信息:

  1. ClipDrawable中内部有一个状态类ClipState,它主要功能是保存原始的Drawable及orientation和gravity信息。
TypedArray a = obtainAttributes(
                r, theme, attrs, com.android.internal.R.styleable.ClipDrawable);

        int orientation = a.getInt(
                com.android.internal.R.styleable.ClipDrawable_clipOrientation,
                HORIZONTAL);
        int g = a.getInt(com.android.internal.R.styleable.ClipDrawable_gravity, Gravity.LEFT);
  • 1

2. 在infalate()方法上面这段代码显示,如果在xml中没有指定clipOrientation默认为HORIZONTAL。如果在xml中没有指定gravity,默认是Gravity.LEFT。

@Override
    protected boolean onLevelChange(int level) {
        mClipState.mDrawable.setLevel(level);
        invalidateSelf();
        return true;
    }


    @Override
    public void draw(Canvas canvas) {

        if (mClipState.mDrawable.getLevel() == 0) {
            return;
        }

        final Rect r = mTmpRect;
        final Rect bounds = getBounds();
        int level = getLevel();
        int w = bounds.width();
        final int iw = 0; //mClipState.mDrawable.getIntrinsicWidth();
        if ((mClipState.mOrientation & HORIZONTAL) != 0) {
            w -= (w - iw) * (10000 - level) / 10000;
        }
        int h = bounds.height();
        final int ih = 0; //mClipState.mDrawable.getIntrinsicHeight();
        if ((mClipState.mOrientation & VERTICAL) != 0) {
            h -= (h - ih) * (10000 - level) / 10000;
        }
        final int layoutDirection = getLayoutDirection();
        Gravity.apply(mClipState.mGravity, w, h, bounds, r, layoutDirection);

        if (w > 0 && h > 0) {
            canvas.save();
            canvas.clipRect(r);
            mClipState.mDrawable.draw(canvas);
            canvas.restore();
        }
    }
  • 1

3. 我们在使用过程是通过ClipDrawable的setLevel()方法,这个方法会触发它的onLevelChange()方法。
在onLevleChange()中,会设置ClipState中的drawable的level。然后刷新自己,这样触发它的onDraw()方法,对自身进行绘制。
在onDraw()中通过获取level,然后计算结合它的方向,计算它显示的矩形范围,然后通过canvas.clipRect()方法。最终完成图片的裁剪显示.

所以归根到底,ClipDrawable的核心就是
setLevel()和Canvas.clipRect()方法。
setLevel()设置显示比例,
然后在onDraw()方法中调用计算出来的矩形进行画面的裁剪,正是通过
canvas.clipRect().

总结

ClipDrawable是一个非常实用的类,合理的运用能让我们节省不少的图片资源,让代码显得整洁与优雅。试想一下,如果没有ClipDrawable去实现一个ProgressBar,我们可能要用多张不同宽度的图片去动态同步进度条的值,而有了CllipDrawable后,我们只要一张图片就可以搞定各种宽度的进度值。当然,我们可以根据实际的开发情况去定制自己的View。

如何使用ClipDrawable实现ImageView图片切换动画 本篇介绍如何使用ClipDrawable来实现简单的图片切换动画,有兴趣的朋友可以看看!! 阅读详情

相关推荐

CLIPDraw:基于CLIP的text-to-vector生成器

CLIP大火的2020年和2021年,引爆了生成式模型的各个领域。今天介绍一项工作,专门用来text-to-vector操作,能够生成不同艺术风格的绘图,不需要任何训练的就能取得非常惊艳的效果,值得深入探讨。

沉迷单车的追风少年 1390

clipDrawable详解

ClipDrawable 是对一个Drawable进行剪切操作,可以控制这个drawable的剪切区域,以及相相对于容器的对齐方式,Android中的进度条就是使用一个ClipDrawable实现效果的,它根据level的属性值,决定剪切区域的大小 ClipDrawable是根据level的大小控制图片剪切操作的 level的大小从0到10000,level为0时完全不显示,为10000时完

xin917480852的博客 1279

ClipDraw: Drawing as a Form of Communicating with AI A

作者:禅与计算机程序设计艺术 1.简介 随着人工智能技术的飞速发展、应用落地及其广泛应用,在智能交互领域取得重大突破,越来越多的人开始重新思考人机交互方式。而语言和画图作为人类和机器沟通的方式,被视作最优秀的通信方式之一。然而,现代人工智能技术面临着巨大的挑战——从文本到图像再到视频,如何让智能体获取到

AI天才研究院 1316

ClipDrawable让开发变得更简单

ClipDrawable让开发更简单Android开发者对Drawable自然是无比熟悉,Drawable代表一类可以绘制的东西,它有许多继承类,常见的就是BitmapDrawable,此外ShapeDrawable,LayerListDrawable也用得比较多,这篇文章讲另外一个比较常见的类ClipDrawable。ClipDrawable非常简单,写博客是因为觉得它非常好用,有时候合理的运用能

frank 的专栏 1万+

Android中实现茶杯注满效果的ClipDrawable技巧

在Android开发中,是一个用于剪裁图像的工具类。它利用level属性来控制图像的可视区域。level属性的值范围在0到10000之间,其中0代表完全不可见,10000代表完全可见。通过改变这个属性的值,我们可以实现图像从完全隐藏到完全显示的平滑过渡,这种特性非常适合用于实现加载动画、进度条等UI效果。当你对设置一个level值时,它会按照其定义的gravity属性来从原始图像中剪裁出一个子区域。gravity属性定义了剪裁的基准位置,比如居中、左对齐、右对齐等。

weixin_34945060的博客 1050

Android ClipDrawable 实现进度条效果

Android使用Drawable资源之使用ClipDrawable资源 实现进入条效果

ClipDrawable类

1,ClipDrawable介绍: 【1】ClipDrawable是通过设置一个Drawable的当前显示比例来裁剪出另一张Drawable, 【2】我们可以通过调节这个比例来控制裁剪的宽高,以及裁剪内容占整个View的权重,通过ClipDrawable的setLevel()方法控制显示比例, 【3】ClipDrawable的level值范围在[0,10000],level的值越...

Cricket_7的博客 541

计算机模拟爆破过程,基于LSDYNA岩石爆破模拟建模分析

原标题:基于LSDYNA岩石爆破模拟建模分析 Ls Dyna岩石爆破模拟仿真作者:dyna_focus擅长领域:dyna/abaqus/hypermesh一、 数值模型的建立1.1 单元及算法的选择岩石,炸药,空气都采用solid164实体单元。岩石采用常应力实体单元,该种单元属于纯粹的lagrange算法,该种算法单元网格附着在材料上,随着材料的流动而产生单元网格的变形,但是在结构变形巨大时,有...

weixin_29494379的博客 7317

Android Drawable之ClipDrawable

OverviewClipDrawable可以根据设置的level值和方向对当前Drawable剪切后显示。它根据level的属性值,决定剪切区域的大小,level的取值范围从0到10000,level为0时完全不显示,为10000时完全显示。(The drawable is clipped completely and not visible when the level is 0 and full

年少的风 2119

AI大模型API中转站选型指南:12项关键指标与实战评估

随着AI大模型技术的快速迭代,企业面临着一个核心挑战:如何在基础模型频繁更新的背景下,为业务系统选择稳定可靠的API中转服务?本文基于真实生产环境测试数据,从12个关键维度系统评估主流API中转站平台,帮助技术团队在模型快速演进的生态中做出科学选型决策。 1. API中转站的核心价值与业务场景 1.1 什么是API中转站 API中转站(API Gateway/Aggregator)是连接业务系统与多个大模型厂商的中间层服务。它通过统一的接口封装了不同厂商的API协议差异,为企业提供标准化的模型调用能力。在实

weixin_29056101的博客 446

陀螺仪选型避坑指南:为什么IMU660RA是智能车竞赛的性价比之选?

本文针对智能车竞赛场景,提供陀螺仪选型避坑指南,并深度解析为何IMU660RA成为性价比之选。文章指出,竞赛选型应避免盲目追求高性能“黑盒”模块,而应注重原始数据获取与算法开发。IMU660RA以其良好的常温稳定性、适中的噪声水平、极致的性价比和丰富的生态支持,成为帮助参赛者深入理解姿态解算原理、进行“白盒开发”的理想教学与实践平台。

tech5的博客 881

ClipDrawable使用

官方文档: A Drawable that clips another Drawable based on this Drawable's current level value. You can control how much the child Drawable gets clipped in width and height based on the level, as well

just do it! 1022

FreeSwitch采用mrcp协议对接科大讯飞asr和tts以及对话系统

FreeSwitch采用mrcp协议对接科大讯飞asr和tts对接过程

shanghaimoon的专栏 8839

Android中ClipDrawable的用法

今天想把drawable下的所有Drawable Resources 弄清楚,看到Clip Drawable 的时候,把以下原文档里的列子考到自己建的项目下 clip.xml <?xml version="1.0" encoding="utf-8"?> <clip xmlns:android=http://schemas.android.com/apk/res/androi...

YUZHIBOYI的专栏 5158

飞腾X100芯片GPU状态查询

本文档对在linux系统下查看X100芯片GPU状态信息进行说明,可以帮助大家了解芯片的实时工作状态。

乌拉大喵喵 2815

OpenClaw更新后变傻了?一分钟教你快速恢复(OpenClaw更新版本后降智、缺少权限问题的解决方案)

OpenClaw 版本更新后出现降智问题,AI不再执行具体任务。本文详细分析问题原因,提供最简便的解决方案✅

XiaoqiangClub的博客 3884

ClipDrawable的使用,图片的徐徐展开效果

clipdrawable的使用

浩宇碧海 3306

第一章 电力电子仿真软件 PLECS简介

PLECS是瑞士Plexim公司开发的电力电子仿真软件,具有快速仿真、丰富元件库和热分析功能。软件提供单机版和嵌入MATLAB的版本,支持多平台安装且流程简单。首次运行需获取授权文件,提供60分钟演示模式。界面包含模型创建、帮助文档和元件库浏览器等功能区域,操作便捷。该软件是专业高效的电力电子系统仿真工具。

501

ClipDrawable

Clip可以译为剪的意思,我们可以把ClipDrawable理解为从位图上剪下一个部分; Android中的进度条就是使用ClipDrawable来实现的,他根据设置level的值来决定剪切 区域的大小,根节点是 clipOrietntion:设置剪切的方向,可以设置水平和竖直2个方向 gravity:从那个位置开始裁剪 drawable:引用的drawable资源,为空的话需要有一个Dra...

jinhuikang的博客 342

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Android中关于ClipDrawable

ClipDrawable是一个可以控制图片显示区域的drawable,他又一个setLevel(全部显示为10000)方法,该方法可以控制显示的比例,对于开始显现的方向,有从左,从右,从中间;对于展开的方向也有水平和竖直。 一个简单的使用: <ImageView android:src="@drawable/clip" android:id="@+id/image" a

前人挖坑,后人种(pen) 632

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Android之ClipDrawable资源简单使用

使用ClipDrawable实现图片徐徐展开效果ClipDrawable 代表从其他位图上截取一个”图片片段” 调用 setLevel(int level) 方法来设置截取的区域大小 当level为0时,截取的图片片段为空; 当level为10000时,截取整张图片。 一开始level默认为0。 以下为源代码在drawable文件下定义一个xml文件<clip xmlns:android=

Abrazen_zz的博客 1341

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

android学习笔记之使用ClipDrawable

ClipDrawable代表从其它位图上截取一个“图片片段”。在XML文件中使用元素定义ClipDrawable对象,可指定如下三个属性: android:drawable:指定截取的源Drawable对象android:clipOrientation:指定截取的方向,可设置为水平截取或垂直截取android:gravity:指定截取时的对齐方式        使用ClipDrawable

Jerry.Column 5004

30 ClipDrawable

ClipDrawable代表从其它位图上截取一个"图片片段",XML中的根元素为<clip.../>,截取的方向由clipOrientation控制 下面以一个慢慢展开的图片为例 先定义一个ClipDrawable资源文件my_clip.xml <?xml version="1.0" encoding="utf-8"?> <clip xmln...

banshan3277的博客 88

ClipDrawable的使用--慢慢展开的图片

ClipDrawable主要的运用用于从其他位图上截取一个“图片片段”。 它在XML的中的根元素为<?xml version="1.0" encoding="utf-8"?> <clip xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_launcher"

jm_heiyeqishi的博客 723
上一篇: 小甜点,RecyclerView 之 ItemDecoration 讲解及高级特性实践
下一篇: Android:最全面的 Webview 详解
Ray534
博客等级 码龄12年 2粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值