Android 图像绘制之 Drawable(二)

Android 图像绘制系列文章
Android图像绘制之Bitmap
Android 图像绘制之 Drawable
Android 图像绘制之 Drawable(二)


在前一篇文章 Android 图像绘制之 Drawable,由于篇幅影响, 只介绍了一些基础的类。当然如果你还没有看上篇文章,我建议你先看下,它会让明白 Drawable 是什么,以及为什么要用 Drawable。 如果你已经看过,那么今天 ,我们玩大点的。

ColorDrawable

这个就是绘制一个纯色背景,用 XML 太浪费 ,直接在代码中创建 ColorDrawable 更简单。

ColorDrawable colorDrawable = new ColorDrawable(Color.GREEN);
imageView.setBackground(colorDrawable);

这个就不上图。

RotateDrawable

从命名上理解,就是可以旋转的 Drawable。

<?xml version="1.0" encoding="utf-8"?>
<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="180"
    android:visible="true">

    <bitmap android:gravity="center"
            android:src="@drawable/sample_1"/>
</rotate>

pivotX 和 pivotY 控制旋转的中心,我们定义为 50%,就是图片的中心位置。 visible 默认是 false,这里我们设置 true。

这里为什么会有 fromDegress 和 toDegress,跟上篇讲的老套路一样,用 level 控制到底旋转多少个角度,所以这两个值其实是一个范围。

如果你仔细看,会发现我是用子节点 <bitmap> 来显示图片的,而没有的 <rotate> 属性中通过 android:drawable显示 。 这个问题我在上篇文章中解释过了,子节点显示图片,可以控制图片不缩放,当图片小于显示区域的时候 ,需要指定 gravity来指明显示的位置。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/test_drawable"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:background="@drawable/rotate_drawable" />

    <SeekBar
        android:id="@+id/test_seekbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/test_drawable"
        android:layout_marginTop="10dp" />

</RelativeLayout>

      final ImageView imageView = (ImageView) findViewById(R.id.test_drawable);
        SeekBar seekBar = (SeekBar) findViewById(R.id.test_seekbar);
        seekBar.setMax(10000);
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                imageView.getBackground().setLevel(i);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

老套路,level 值的范围是 0 到 10000

RoundedBitmapDrawable

其实这个名字应该叫做 圆角图片,它是设置图片四个角的圆形半径。当图片是矩形的时候,就有四个圆角,再特殊一点,如果图片是正方形,正好圆角的半径为正方形边长的一半,那么它就是一个圆。

有了这些分析,现在我来创建一个圆形图片,还是用上面那个性感美女的图片做背景,不过图片很大,我们需要截取美女的头部作为图像。

        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample_5);
        // 创建 600*600 正方形 Bitmap,截取头像部分
        Bitmap newBitmap = Bitmap.createBitmap(bitmap,
                bitmap.getWidth() / 2 - 600 / 2, //x
                100,// y
                600,//width
                600//height
        );
        // 回收没有用的 bitmap
        bitmap.recycle();
        RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(), newBitmap);
        roundedBitmapDrawable.setCornerRadius(newBitmap.getWidth() / 2);
        imageView.setImageDrawable(roundedBitmapDrawable);

如果你对 Bitmap 操作还不熟悉的,可以参考我之前文章 Android图像绘制之Bitmap

看过我之前文章后,可能有人会问,你加载图为什么没有用 Options.inSampleSize 压缩,综合考虑有两个原因。

  1. 压缩后,图片就不是那么清晰了,我需要一个清晰的圆形图像。
  2. 我在创建了 newBitmap 后,把占用内存大的 bitmap 回收了,bitmap.recycle()。


ShapeDrawable

上篇文章中,我们用 GradientDrawable 在 XML 中绘制基本图形(直线,椭圆,矩形,圆环)。现在我们可以用 ShapeDrawable 试试,ShapeDrawable 可以绘制 Arc(扇形),oval(椭圆),Path(路径), 矩形(rect),圆角矩形(RoundRectShape)。这里我只举两个例子,显示一个圆形图片和一个菱形图片,其它的大家自己动手试试。

椭圆或者圆形

我们再来绘制一个圆形图片

        ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape());
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample_5);
        BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        shapeDrawable.getPaint().setShader(shader);
        imageView.setBackground(shapeDrawable);

这里我们利用了 Shader (着色器),我现在还没有介绍,大家可以网上搜搜看怎么用。

是不是发现,有时候显示一个圆形图片其实就是这么简单。

路径

        // 解析 Bitmap 的宽
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(getResources(), R.drawable.sample_5, options);
        int imageWidth = options.outWidth;
        // Path
        Path path = new Path();
        path.moveTo(imageWidth, 0);
        path.lineTo(imageWidth * 2, imageWidth);
        path.lineTo(imageWidth, imageWidth * 2);
        path.lineTo(0, imageWidth);
        path.close();
        ShapeDrawable shapeDrawable = new ShapeDrawable(new PathShape(path, imageWidth * 2, imageWidth * 2));
        // 设置 shader
        Paint paint = shapeDrawable.getPaint();
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample_5);
        BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        paint.setShader(shader);
        
        imageView.setBackground(shapeDrawable);

这里涉及的东西有点多,path,shader,不过目前你知道有这种效果就好。


PaintDrawable

PaintDrawable 是继承自 ShapeDrawable。 抛开 ShapeDrawable 的功能,PaintDrawable 就是给背景画圆角,这里就不演示了,其实小伙伴在学习的时候 ,要多动动手写代码,只看不写,其实效果并没有想象中的好。

RippleDrawable

波纹效果的 Drawable,再介绍这个之前 ,我们先看看 5.0 之后 ,系统默认的波纹效果

无边界波纹效果

RippleDrawable 是继承自 LayerDrawable 的,如果一个 Layer 层都没有的话,就是无边界效果

<?xml version="1.0" encoding="utf-8"?>
<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorAccent">
</ripple>

为 Button 设置背景

    <Button
        android:layout_centerInParent="true"
        android:background="@drawable/ripple_drawable"
        android:text="自定义波纹效果"
        android:id="@+id/imageview"
        android:layout_width="match_parent"
        android:layout_height="100dp"/>

有边界效果

如果加了一个图层作为背景就会有边界效果。

<?xml version="1.0" encoding="utf-8"?>
<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorAccent">

    <item android:drawable="@drawable/bird"/>
</ripple>

我们再把效果做得接近于系统点,用一个灰色纯色做背景

<?xml version="1.0" encoding="utf-8"?>
<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorAccent">

    <item android:drawable="@drawable/ripple_shape_drawable"/>
</ripple>

ripple_shape_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#b4abab"/>
    <corners android:radius="40dp"/>
</shape>

Ripple 还有加上一个 mask layer 的东西,但是我查了下,没有叼用啊,什么情况?

结束

还有几个 Drawable 类我没演示,主要是还有点烦琐,以后可能说另开一篇讲解。 如果小伙伴有什么疑问,可以下方评论。



作者:不惜留恋_
链接:https://www.jianshu.com/p/4134e2352d65
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值