【Kotlin】Android保存任意View为图片至系统图库—附demo源码

本文以少量的代码,演示了无需声明权限、仅10余行代码即可保存任意View为图片的简洁方法,demo源码链接附在文末

特别说明:

        本文采用分—总结构展示代码,即先展示局部代码,并说明其用法和作用;小节结尾处再给出该部分对应文件的完整代码布局XML文件在方法实现之后。

一、方法实现

        分两步完成:

  1. 转换View对象为Bitmap位图对象
  2. 将Bitmap位图对象保存为图片

        在MainActivity文件中:

1.将View转换为Bitmap位图

/** 创建位图 */
fun createViewBitmap(view: View): Bitmap? {
    val bitmap = Bitmap.createBitmap(
        view.width, view.height,
        Bitmap.Config.ARGB_8888
    )
    val canvas = Canvas(bitmap)
    view.draw(canvas)
    return bitmap
}
Bitmap.createBitmap(参数1,参数2,参数3)

        这是内置的方法,直接调用即可将View对象转化为一个Bitmap位图对象

参数1:生成的Bitmap位图对象的宽,可使用当前View实际呈现的宽度,也可自行指定

参数2:生成的Bitmap位图对象的高,可使用当前View实际呈现的高度,也可自行指定

参数3:指定Bitmap位图对象的存储方案:本文采用Bitmap.Config.ARGB_8888

位图存储方案简介:A指alpha透明通道,RGB指红绿蓝三通道。

  1. ARGB_8888:四通道均采用8bit存储,质量最高,体积最大
  2. ARGB_4444:四通道均为4bit存储,据说失真较严重
  3. RGB_565:不包含透明通道,不支持透明度,但质量较好,体积仅ARGB_8888的一半
  4. ALPHA_8:不包含颜色值,仅存储alpha透明度

一般情况下,若无需透明度,选择RGB_565,可节省空间,需要透明度,选择ARGB_8888

更多细节敬请参见这位博主的文章


 2.保存Bitmap位图为图片

/** 保存为图片 */
    fun saveImage(view: View) {
        // 调用上一步的转换位图函数
        val imageBit = createViewBitmap(view)
        // 保存至系统图库
        MediaStore.Images.Media.insertImage(contentResolver,imageBit, "picture_name", "demo_saveImage")
    }
MediaStore.Images.Media.insertImage(contentResolver, 参数1, 参数2, 参数3)

        也是一个内置的方法,在Activity中可以直接调用,contentResolver是固定传入对象。

参数1:位图对象Bitmap

参数2:图片名称,可以在系统图库的详情页面查看到

参数3:图片的描述信息


3.设置点击事件

// 布局XML文件在后文
// 分别绑定根布局和”保存图片”按钮
val layout = findViewById<ConstraintLayout>(R.id.layout)
val button = findViewById<Button>(R.id.save_button)

// 设置“保存图片”按钮的点击
button.setOnClickListener {
    saveImage(layout)
}

   MainActivity的完整代码 

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 分别绑定根布局和”保存图片”按钮
        val layout = findViewById<ConstraintLayout>(R.id.layout)
        val button = findViewById<Button>(R.id.save_button)

        // 设置“保存图片”按钮的点击
        button.setOnClickListener {
            saveImage(layout)
        }
    }

    /** 创建位图 */
    fun createViewBitmap(view: View): Bitmap? {
        val bitmap = Bitmap.createBitmap(
            view.width, view.height,
            Bitmap.Config.ARGB_8888
        )
        val canvas = Canvas(bitmap)
        view.draw(canvas)
        return bitmap
    }

    /** 保存为图片 */
    fun saveImage(view: View) {
        val imageBit = createViewBitmap(view)
        MediaStore.Images.Media.insertImage(contentResolver,imageBit, "picture_name", "demo_saveImage")
    }
}

4.真机测试结果


二、布局设置

        本文使用约束布局,简单的设置了1个文本框,1个“保存图片”按钮。

1.设置“保存图片”按钮id为:save_button

2.设置根布局id为:layout

3.设置根布局的背景颜色为系统自带的白色:@color/white

第3步不是必须的,只是因为若不设置背景颜色,则默认透明,图片背景将显示为黑色,不利于观察)

        activity_main.xml文件的完整代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:id="@+id/layout"
    android:background="@color/white">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/save_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="保存图片"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.8" />

</androidx.constraintlayout.widget.ConstraintLayout>

三、补充说明

        之所以无需声明存储权限,是因为此图片存储于共享存储空间中,这是系统提供的公共目录,由系统进行管理。详情敬请参阅官方说明文档官方说明文档官方说明文档

        在其他博主的文章中有反映到,此方法生成的图片不能在图库中立刻查看到,还需进行广播,通知图库进行更新,但实际测试结果中并未出现此问题。 

MediaStore.Images.Media.insertImage(contentResolver, 参数1, 参数2, 参数3)

        此方法在 API level 29 以上实际已被弃用,但并不是因为不安全而被弃用,此方法依旧是可以正常使用的,只是谷歌官方推出了可以更好控制生命周期的方法,有机会再写文章进行说明。

        除此方法外,还可将指定位置下的图片保存至系统图库。

MediaStore.Images.Media.insertImage(contentResolver, "image path", "title", "description")

如有任何疑问,请在评论区留言,我会努力回复。

demo源码链接如下:

github地址:https://github.com/darlingxyz/demo_saveImage

gitee地址:https://gitee.com/darlingxyz/demo_saveImage

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值