Android图形图像相关小知识点整理

文章目录

TransitionDrawable

定义两个Drawable之间渐变过渡,A->B(startTransition) ,B->A(reverseTransition)

方式 1:

<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/back_local_hdd_cover"/>
    <item android:drawable="@drawable/back_local_bt_cover"/>
</transition>

方式 2:

        val arrayDrawable= arrayOf(
        ResourcesCompat.getDrawable(resources, R.drawable.back_local_hdd_cover, null),
        ResourcesCompat.getDrawable(resources, R.drawable.back_local_bt_cover, null)
        )

        val transitionDrawable = TransitionDrawable(arrayDrawable)
    private fun newTransactionDrawable() {
        setContentView(R.layout.activity_drawable)
        val transition = ResourcesCompat.getDrawable(
            resources,
            R.drawable.expand_collapse,
            null
        ) as TransitionDrawable

        iv_drawable.apply {
            setImageDrawable(transition)
            contentDescription = resources.getString(R.string.app_name)
        }.setOnClickListener {
            isChecked = if (!isChecked) {
                transition.startTransition(1000)
                true
            } else {
                transition.reverseTransition(1000)
                false
            }
        }
    }

ShapeDrawable

动态绘制二维图形

class CustomDrawableView(context: Context) : View(context) {
    private val drawable: ShapeDrawable = run {
        val x = 100
        val y = 100
        val width = 300
        val height = 300

        val shape: ShapeDrawable = ShapeDrawable(OvalShape()).apply {
            // If the color isn't set, the shape uses black as the default.
            paint.color = 0xff74AC23.toInt()
            // If the bounds aren't set, the shape can't be drawn.
            setBounds(x, y, x + width, y + height)
        }
        shape
    }

    override fun onDraw(canvas: Canvas) {
        drawable.draw(canvas)
    }
}

xml中定义shape图片,只需要记住一些关键属性即可,可以查阅属性文档 AndroidDeveloper的Shape属性文档

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <corners android:radius="10dp" />
    <stroke
        android:width="10dp"
        android:color="@color/color_pink"
        android:dashWidth="6dp"
        android:dashGap="6dp" />
    <gradient
        android:angle="90"
        android:centerColor="@color/reply_red_200"
        android:centerX="0.7"
        android:centerY="0.7"
        android:endColor="@color/white"
        android:startColor="@color/color_pink" />
    <padding
        android:left="100dp"
        android:right="100dp" />
</shape>

Tint给图片着色

对图片进行着色,一般使用在Icon中使用(背景透明的图标)只会给有色值的图标部分着色,可以在代码中使用 setTint() 方法对 BitmapDrawableNinePatchDrawableVectorDrawable 对象着色

Android图形图像相关小知识点整理

经过tint着色之后:

Android图形图像相关小知识点整理

    <ImageView
        android:id="@+id/repeat_all"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:contentDescription="@string/app_name"
        android:src="@drawable/ic_repeat_round"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:tint="@color/color_pink"
        tools:ignore="UnusedAttribute" />

tint有以下几种模式,一般使用默认模式(src_in)即可

        <attr name="tintMode">
            <!-- The tint is drawn on top of the drawable.
                 [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
            <enum name="src_over" value="3" />
            <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
                 color channels are thrown out. [Sa * Da, Sc * Da] -->
            <enum name="src_in" value="5" />
            <!-- The tint is drawn above the drawable, but with the drawable’s alpha
                 channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
            <enum name="src_atop" value="9" />
            <!-- Multiplies the color and alpha channels of the drawable with those of
                 the tint. [Sa * Da, Sc * Dc] -->
            <enum name="multiply" value="14" />
            <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
            <enum name="screen" value="15" />
            <!-- Combines the tint and drawable color and alpha channels, clamping the
                 result to valid color values. Saturate(S + D) -->
            <enum name="add" value="16" />
        </attr>
    private fun newTintDrawable() {
        //1、xml使用
        setContentView(R.layout.activity_tint)
        //2、代码中对ImageView使用
        repeat_shuffle.imageTintList =
            ColorStateList.valueOf(ContextCompat.getColor(this, R.color.color_pink))
        repeat_shuffle.imageTintMode = PorterDuff.Mode.SRC_IN
        repeat_shuffle.setImageResource(R.drawable.ic_repeat_shuffle_round)
        //3、BitmapDrawable使用
        val rawBitmap = BitmapFactory.decodeResource(
            resources,
            R.drawable.ic_repeat_shuffle_round
        )
        val drawable: Drawable = BitmapDrawable(rawBitmap)
        drawable.setTint(ResourcesCompat.getColor(resources, R.color.color_pink, null))
        repeat_shuffle.setImageDrawable(drawable)
        //4、TransitionDrawable使用
        val arrayDrawable = arrayOf(
            ResourcesCompat.getDrawable(resources, R.drawable.ic_repeat_shuffle_round, null),
            ResourcesCompat.getDrawable(resources, R.drawable.ic_repeat_round, null)
        )
        val transitionDrawable = TransitionDrawable(arrayDrawable)
        transitionDrawable.setTintMode(PorterDuff.Mode.SRC_IN)
        transitionDrawable.setTint(ResourcesCompat.getColor(resources, R.color.color_pink, null))
        repeat_shuffle.setImageDrawable(transitionDrawable)
    }

Palette提取图片颜色

我们需要通过一个Bitmap对象来生成一个对应的Palette对象。调用generate()以同步的方式生成Palette,或者generate(object :Palette.PaletteAsyncListener )以异步的方式生成Palette

    // 同步generate()方式获取
        val palette = Palette.from(rawBitmap).generate()
        val darkVibrantColor = palette.getDarkVibrantColor(Color.BLACK)
        iv_palette.setBackgroundColor(darkVibrantColor)
    // 异步generate()方式获取
        Palette.from(rawBitmap).generate { palette ->
            if (palette != null) {
                iv_palette2.setBackgroundColor(palette.getDarkVibrantColor(Color.BLACK))
            }
        }

得到Palette对象后,就可以拿到提取到的颜色值

● Palette.getVibrantSwatch() (有活力的)
● Palette.getDarkVibrantSwatch() (有活力的 暗色)
● Palette.getLightVibrantSwatch() (有活力的 亮色)
● Palette.getMutedSwatch() (柔和的)
● Palette.getDarkMutedSwatch() (柔和的 暗色)
● Palette.getLightMutedSwatch() (柔和的 亮色)

● Palette.getDominantSwatch() (占优势的颜色)

以上方法都有对应的getColor()方法,例如: **getDominantColor(@ColorInt int defaultColor) **

一般使用getDominantColor便可拿到优势色值

Android图形图像相关小知识点整理

如需访问Palette中的所有颜色,可以使用 getSwatches() 方法返回从图片生成的所有色样的列表,包括标准的六种颜色配置文件

VectorDrawable

VectorDrawable 定义静态可绘制对象,由 pathgroup 对象构成

    <!-- res/drawable/battery_charging.xml -->
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        <!-- intrinsic size of the drawable -->
        android:height="24dp"
        android:width="24dp"
        <!-- size of the virtual canvas -->
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
       <group
             android:name="rotationGroup"
             android:pivotX="10.0"
             android:pivotY="10.0"
             android:rotation="15.0" >
          <path
            android:name="vect"
            android:fillColor="#FF000000"
            android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33V9h4.93L13,7v2h4V5.33C17,4.6 16.4,4 15.67,4z"
            android:fillAlpha=".3"/>
          <path
            android:name="draw"
            android:fillColor="#FF000000"
            android:pathData="M13,12.5h2L11,20v-5.5H9L11.93,9H7v11.67C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V9h-4v3.5z"/>
       </group>
    </vector>
    

AnimatedVectorDrawable

可为矢量图形的属性添加动画,可以将添加动画效果之后的矢量图形定义为三个单独的资源文件,也可以将其定义为可定义整个可绘制对象的单个 XML 文件

多个 XML 文件

  1. VectorDrawable XML 文件

  2. AnimatedVectorDrawable XML 文件,用于定义目标 VectorDrawable、要添加动画效果的目标路径和组、属性

  3. 定义为 ObjectAnimatorAnimatorSet 对象的动画文件

    AnimatedVectorDrawable 的 XML 文件
    
    <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
           android:drawable="@drawable/vd" >
             <target
                 android:name="rotationGroup"
                 android:animation="@anim/rotation" />
             <target
                 android:name="vectorPath"
                 android:animation="@anim/path_morph" />
        </animated-vector>
        
    

    单个 XML 文件

        <animated-vector
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:aapt="http://schemas.android.com/aapt">
            <aapt:attr name="android:drawable">
                <vector
                    android:width="24dp"
                    android:height="24dp"
                    android:viewportWidth="24"
                    android:viewportHeight="24">
                    <path
                        android:name="root"
                        android:strokeWidth="2"
                        android:strokeLineCap="square"
                        android:strokeColor="?android:colorControlNormal"
                        android:pathData="M4.8,13.4 L9,17.6 M10.4,16.2 L19.6,7" />
                </vector>
            </aapt:attr>
            <target android:name="root">
                <aapt:attr name="android:animation">
                    <objectAnimator
                        android:propertyName="pathData"
                        android:valueFrom="M4.8,13.4 L9,17.6 M10.4,16.2 L19.6,7"
                        android:valueTo="M6.4,6.4 L17.6,17.6 M6.4,17.6 L17.6,6.4"
                        android:duration="300"
                        android:interpolator="@android:interpolator/fast_out_slow_in"
                        android:valueType="pathType" />
                </aapt:attr>
            </target>
        </animated-vector>
        
    

    矢量图标的优点

    1、矢量图的主要优势在于图片可缩放。可以在不降低显示质量的情况下缩放图片,也就是说,可以针对不同的屏幕密度调整同一文件的大小,而不会降低图片质量。

    2、不仅能缩减 APK 文件大小,还能减少开发者维护工作。

    3、矢量图是以xml语言来描述的,所以它修改自如。

    矢量图标的缺点

    对cpu的消耗,图片越大绘制占用的cpu资源越多,官方建议不超过200dp*200dp

    官方建议

    • 矢量可绘制对象可伸缩,不会失去定义,是单色应用内图标的理想之选。

    • 尽管矢量可绘制对象确实支持一种或多种颜色,但在很多情况下,最好将图标颜色设置为黑色通过对可绘制对象进行着色,可以将位图定义为透明遮罩,并在运行时用一种颜色对其进行着色。(Tint)

    • 颜色提取用于自动从位图图片中提取突出颜色。(palette)

LayerDrawable

使用标签< layer-list> + item,实现叠加效果,可以由多个Drawable的叠加生成一个Drawable,可以减少不必要的代码层级,图二的叠加效果需要在父层级设置android:clipChildren=“false”

Android图形图像相关小知识点整理
Android图形图像相关小知识点整理

上图阴影效果如下:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
 <item
     android:left="6dp"
     android:top="6dp">
     <shape android:shape="rectangle">
         <solid android:color="#1A000000" />
         <corners
             android:bottomLeftRadius="6dip"
             android:bottomRightRadius="6dip"
             android:topLeftRadius="6dip"
             android:topRightRadius="6dip" />
     </shape>
 </item>
 <item
     android:bottom="10dp"
     android:right="10dp">
     <shape android:shape="rectangle">
         <solid android:color="#f46464" />
         <corners
             android:bottomLeftRadius="6dip"
             android:bottomRightRadius="6dip"
             android:topLeftRadius="6dip"
             android:topRightRadius="6dip" />
     </shape>
 </item>
</layer-list>

Demo示例

GitHub地址,查看DrawableActivity类

参考文献

Google官方地址:https://developer.android.google.cn/guide/topics/graphics/drawables

上一篇:给定一个数组arr,返回arr的最长无重复元素子数组的长度


下一篇:CSS背景以及选择器的知识