Android自定义视图中图片的处理

目录
  • 1.使用Drawable对象
  • 2.Bitmap和BitmapFactory
    • 2.1 例子
    • 2.2 额外知识点(assets)
    • 2.3 代码更严谨
  • 3.Android9新增的ImageDecoder
    • 3.1 例子

所谓游戏,本质就是提供更逼真的、能模拟某种环境的用户界面,并根据某种规则来响应用户操作。为了提供更逼真的用户界面,需要借助于图形、图像处理。

从广义的角度来看,Android应用中的图片不仅包括*.png、*.jpg、 *.gif等各种格式的位图,也包括使用XML资源文件定义的各种Drawable对象。

1.使用Drawable对象

为Android应用增加了Drawable资源之后,Android SDK会为这份资源在R清单文件中创建一个索引项:R.drawable.file_name。

获取方式:

  • 在XML资源文件中通过@drawablelfile_name访问该Drawable对象
  • 在Java代码中通过R.drawable.file_name访问该Drawable对象。

需要指出的是,R.drawable.file_name是一个int类型的常量,它只代表Drawable对象的ID,如果Java程序中需要获取实际的Drawable对象,则可调用Resources的getDrawable (int id)方法来实现。

2.Bitmap和BitmapFactory

Bitmap代表一个位图,BitmapDrawable里封装的图片就是一个Bitmap对象。

两者之间的转换:

//把一个Bitmap对象包装成BitmapDrawable对象
BitmapDrawable drawable = new BitmapDrawable (bitmap) ;

如果需要获取BitmapDrawable所包装的Bitmap对象,则可调用BitmapDrawable的getBitmap ()方法,如下面的代码所示:

//获取BitmapDrawable所包装的Bitmap 对象
Bitmap bitmap = drawable.getBitmap();

新建Bitmap对象的一些方法:

  • createBitmap (Bitmap source,int x, int y,int width,int height):从源位图source的指定坐标点(给定x、y)开始,从中“挖取"宽width、高height的一块出来,创建新的Bitmap对象。
  • createScaledBitmap (Bitmap src, int dstWidth,int dstHeight,boolean filter) :对源位图src进行缩放,缩放成宽dstWidth、高dstHeight的新位图。 filter是过滤器。
  • createBitmap (int width,int height,Bitmap.Config config):创建一个宽width、高height的新位图。
  • createBitmap (Bitmap source,int x, int y, int width,int height,Matrixm, boolean filter):从源位图source 的指定坐标点(给定x、y)开始,从中“挖取"宽 width、高height的一块出来,创建新的Bitmap对象,并按Matrix指定的规则进行变换。

Bitmap.Config类,在Bitmap类里createBitmap(int width, int height, Bitmap.Config config)方法里会用到,打开个这个类一看 :枚举变量

public static final Bitmap.Config ALPHA_8

public static final Bitmap.Config ARGB_4444

public static final Bitmap.Config ARGB_8888

public static final Bitmap.Config RGB_565

BitmapFactory是一个工具类,它提供了大量的方法,这些方法可用于从不同的数据源来解析、创建Bitmap对象。BitmapFactory包含了如下方法。

  • decodeByteArray (byte[]data,int offset,int length)︰从指定字节数组的offset位置开始,将长度为length的字节数据解析成Bitmap对象。
  • decodeFile (String pathName) :从pathName指定的文件中解析、创建Bitmap对象。
  • decodeFileDescriptor (FileDescriptor fd):用于从FileDescriptor对应的文件中解析、创建Bitmap对象。
  • decodeResource (Resources res,int id) :用于根据给定的资源ID从指定资源中解析、创建Bitmap对象。
  • decodeStream (InputStream is):用于从指定输入流中解析、创建Bitmap对象。

对于创建而言,对应的就是回收了。如果系统不停的去解析、创建Bitmap对象,可能由于创建的Bitmap所占用的内存还没回收,而导致OOM。

  • boolean isRecycled ():返回该Bitmap对象是否已被回收。
  • void recycle () :强制一个Bitmap对象立即回收自己。

如果Android应用需要访问其他存储路径(比如SD卡)里的图片,那么都需要借助于BitmapFactory来解析、创建Bitmap对象。

2.1 例子

下面开发一个查看/assets/目录下图片的图片查看器,当用户单击该按钮时程序会自动去搜寻/assets/目录下的下—张图片。此处不再给出界面布局代码,该程序的代码如下。

public class Test4Activity extends Activity {
    String[] images = null;
    AssetManager assets = null;
    int currentImg = 0;
    private ImageView image;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test4_acitvity);
        image = findViewById(R.id.test4_iv);
        Button next = findViewById(R.id.test4_bt_next);
        try {
            assets = getAssets();
            //获取assets目录目录下的所有文件
            images =assets.list("");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //按钮事件
        next.setOnClickListener(view -> {
            //如果发生数组越界
            if(currentImg >= images.length){
                currentImg = 0;
            }
            //找到下一个图片文件
            while (!images[currentImg].endsWith(".png")&&!images[currentImg].endsWith(".jpg")
                    &&!images[currentImg].endsWith(".gif")){
                currentImg++;
                //如果已经发生了数组越界
                if(currentImg >= images.length){
                    currentImg = 0;
                }
            }
            InputStream assetFile = null;
            try {
                //打开指定资源对应的输入流
                assetFile = assets.open(images[currentImg++]);
            } catch (IOException e) {
                e.printStackTrace();
            }
            BitmapDrawable bitmapDrawable = (BitmapDrawable) image.getDrawable();
            //如果图片还未回收,先强制回收该图片
            if(bitmapDrawable != null&&!bitmapDrawable.getBitmap().isRecycled()){
                bitmapDrawable.getBitmap().recycle();
            }
            //改变ImageView显示图片
            //调用了BitmapFactory从指定输入流解析并创建Bitmap
            image.setImageBitmap(BitmapFactory.decodeStream(assetFile));
        });
    }
}

2.2 额外知识点(assets)

系统为每一个新设计的程序提供了/assets文件夹,这个文件夹保存的文件能够打包在程序里。

/res和/assets的不同点是,android不为/assets下的文件生成ID。假设使用/assets下的文件,须要指定文件的路径和文件名称。怎样访问/assets下的内容?

例如,假设在assets目录下有一个名称为filename的文件,那么就可以使用以下代码来访问它:

AssetManager assset= getAssets();
InputStream is = assset.open("filename");

2.3 代码更严谨

1.发现这代码一点黄色都没有,证明很严谨。

注意为什么button放在了里面,而imageView放在了外面。

将button放在外面会有Field can be converted to a local variable的警告,意思是检测到这个变量可以使用局部变量替换,建议删除并写成局部变量。就是其他地方也没有使用到它,没有必要声明成成员变量。

2.设计到数组访问,一定要防止其数组越界。上面还搞了两个。

assetFile = assets.open(images[currentImg++]);

此时进入到open的必定是图片资源的name,用了之后currentImg自加,探索下一个图片。第一个防止其数组越界的判断就是防这里的;第二是对应着判断不是图片资源的++。但是这个代码还有问题:假如里面有资源,但是都不是图片资源。那就会进入死循环

3.在显示图片之前,一定要释放之前的Bitmap,以免OOM

释放的判断的条件是使用Bitmap的封装类。

3.Android9新增的ImageDecoder

Android 9 引入了 ImageDecoder、OnHanderDecodedListener 等API,提供了更强大的图片解码支持,可以解码png、jpeg等静态图片和gif、webp等动画图片。另外。还新增了支持HEIF格式:

HEIF格式:这种压缩格式据有超高的压缩比例,相比JPEG,可以压缩到其一半大小,而且可以保证其近似的图片质量。

当使用 ImageDecoder 解码gif、webp等动画图片时,会返回一个AnimatedImageDrawable对象,调用AnimatedImageDrawable对象的start()方法即可开始执行动画。

ImageDecoder 解码图片的方式:

  • 调用 ImageDecoder 的重载的 createSource 方法来创建 Source 对象。根据不同的图片来源, createSource 方法有不同的重载模式。
  • 调用ImageDecoder 的 decodeDrawabIe(Source) or decodeBitmap(Source)方法来读取代表图片的 Drawable或 Bitmap对象。

在第二步时,可以额外传入一个OnHanderDecodedListener参数,该参数代表了监听器,该监听器要实现一个 onHanderDecoded(ImageDecoder,ImageInfo,Source)方法,可以对ImageDecoder进行额外的设置,也可以通过 ImageInfo 获取被解码图片的信息。

3.1 例子

public class Test5Activity extends AppCompatActivity {
    //说白了只有api 28 之后的才进的来
    @RequiresApi(api = Build.VERSION_CODES.P)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test5);
        //获取对象
        TextView textView = findViewById(R.id.test5_tv);
        ImageView imageView = findViewById(R.id.test5_iv);
        //创建 imageDecoder.Source对象
            //第一步:
            ImageDecoder.Source source = ImageDecoder.createSource(getResources(),R.drawable.viewgif);
            try {
                //第二步:执行decodeDrawable()方法获取Drawable对象
                @SuppressLint({"WrongThread", "SetTextI18n"})
                Drawable drawable = ImageDecoder.decodeDrawable(source,(decoder, info, s) ->{
                    //通过 info 参数获取被解码图片的信息
                    textView.setText("图片的原始宽度:"+info.getSize().getWidth()+
                            "\n"+"图片原始宽高"+info.getSize().getHeight());
                    //设置图片解码之后的缩放大小
                    decoder.setTargetSize(600,580);
                });
                imageView.setImageDrawable(drawable);
                //如果drawable 是AnimatedImageDrawable的实例,则执行动画
                if(drawable instanceof AnimatedImageDrawable){
                    ((AnimatedImageDrawable) drawable).start();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
}

与传统的BitmapFactory相比,ImageDecoder 甚至可以解码包含不完整或错误的图片,如果希望显示ImageDecoder解码出错之前的部分图片,则可通过为 ImageDecoder没置OnPartialImageListener监听器来实现。例如如下代码片段:

//先用Lambda 表达式作为OnHeaderDecodeListener监听器
    Drawable drawable = ImageDecoder.decodeDrawable(source,(decoder, info, s) ->{
        //为ImageDecoder 设置 OnPartialImageListener 监听器(Lambda 表达式)
        decoder.setOnPartialImageListener(e->{
            ....
            //return true 表明即使不能完整地解码全部图片也返回Drawable或Bitmap
            return true;
        });
    });

到此这篇关于Android自定义视图中图片的处理的文章就介绍到这了,更多相关Android图片内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android实现图片九宫格

    本文实例为大家分享了Android实现图片九宫格的具体代码,供大家参考,具体内容如下 九宫格分三类 实现的效果 具体实现 activity_main <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.

  • Android不压缩图片实现高清加载巨图实例

    目录 一.概述 二.初识BitmapRegionDecoder 三.自定义显示大图控件 四.测试 参考链接 一.概述 对于加载图片,大家都不陌生,一般为了尽可能避免OOM都会按照如下做法: 对于图片显示:根据需要显示图片控件的大小对图片进行压缩显示.如果图片数量非常多:则会使用LruCache等缓存机制,将所有图片占据的内容维持在一个范围内. 其实对于图片加载还有种情况,就是单个图片非常巨大,并且还不允许压缩.比如显示:世界地图.清明上河图.微博长图等. 那么对于这种需求,该如何做呢? 首先不压

  • Android实现左右滑动切换图片

    简要说明 本文采用ImageSwitcher实现左右滑动切换图片.首先调用setFactory方法,设置视图工厂:然后设置手指触碰监听,判断左滑右滑进而切换图片. 本地图片 xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:too

  • Android性能优化之图片大小,尺寸压缩综合解决方案

    目录 前言 常见的图片压缩方法 质量压缩 尺寸压缩 libjpeg 图片压缩流程 总结 前言 在Android中我们经常会遇到图片压缩的场景,比如给服务端上传图片,包括个人信息的用户头像,有时候人脸识别也需要捕获图片等等.这种情况下,我们都需要对图片做一定的处理,比如大小,尺寸等的压缩. 常见的图片压缩方法 质量压缩 尺寸压缩 libjpeg 质量压缩 首先我们要介绍一个api--Bitmap.compress() @WorkerThread public boolean compress(Co

  • Android开发实现图片大小与质量压缩及保存

    目录 Android中图片有四种属性 Android目前常用图片格式 使用 大小压缩 质量压缩 混合方式压缩 采样率压缩 图片保存到本地 Android中图片有四种属性 ALPHA_8:每个像素占用1byte内存 ARGB_4444:每个像素占用2byte内存 ARGB_8888:每个像素占用4byte内存 (默认) RGB_565:每个像素占用2byte内存 Android默认的颜色模式为ARGB_8888,这个颜色模式色彩最细腻,显示质量最高.但同样的,占用的内存也最大.所以在对图片效果不是

  • Android实现手势划定区域裁剪图片

    本文实例为大家分享了Android实现手势划定区域裁剪图片的具体代码,供大家参考,具体内容如下 需求: 拍照,然后对图片进行处理,划定矩形区域,将矩形区域裁剪下来 思路: 1.使用系统相机拍照,拍完返回,对图片进行压缩和存储. 2.新建一个activity处理图片裁剪,利用自定义view在画布上画出矩形区域. 3.根据坐标信息生成裁剪图片并存储. 部分核心代码: 1.调用系统相机拍照 String IMAGE_PATH = Environment.getExternalStorageDirect

  • AndroidStudio实现能在图片上涂鸦程序

    本文实例为大家分享了AndroidStudio实现能在图片上涂鸦的具体代码,供大家参考,具体内容如下 一.内容:设计一个能在图片上涂鸦的程序 二.实现 1. 布局文件activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    

  • Android studio实现左右滑动切换图片

    本文实例为大家分享了Android studio实现左右滑动切换图片的具体代码,供大家参考,具体内容如下 切换图片首先要使用到图片切换器ImageSwitcher 先了解一下ImageSwitcher 1.ImageSwitcher的重要属性: android:inAnimation:切入图片时的效果.android:outAnimation:切出图片时的效果. 以上两个属性在XML中设定,可以通过XML资源文件自定义动画效果,如果只是想使用Android自带的一些简单的效果,调用Android

  • Android实现图片预览与保存功能

    目录 前言 引入插件 总结 前言 在App开发中,通常为了省流提高加载速度提升用户体验我们通常在列表中或新闻中的插图都是以缩略图压缩过的图片来进行展示,当用户点击图片时我们再去加载真正像素的大图让用户预览,如果用户想保存并且可以保存到自己的相册中,那么在Flutter中如何实现这样的功能,看完这篇文章让你1分钟瞬间实现. 引入插件 首先,我们需要引入强大的Flutter社区中的两个插件,分别是: photo_view: ^0.13.0 用来加载查看大图. image_gallery_saver:

  • Android自定义视图中图片的处理

    目录 1.使用Drawable对象 2.Bitmap和BitmapFactory 2.1 例子 2.2 额外知识点(assets) 2.3 代码更严谨 3.Android9新增的ImageDecoder 3.1 例子 所谓游戏,本质就是提供更逼真的.能模拟某种环境的用户界面,并根据某种规则来响应用户操作.为了提供更逼真的用户界面,需要借助于图形.图像处理. 从广义的角度来看,Android应用中的图片不仅包括*.png.*.jpg. *.gif等各种格式的位图,也包括使用XML资源文件定义的各种

  • Android自定义View中attrs.xml的实例详解

    Android自定义View中attrs.xml的实例详解 我们在自定义View的时候通常需要先完成attrs.xml文件 在values中定义一个attrs.xml 然后添加相关属性 这一篇先详细介绍一下attrs.xml的属性. <?xml version="1.0" encoding="utf-8"?> <resources> //自定义属性名,定义公共属性 <attr name="titleText" for

  • Android 自定义imageview实现图片缩放实例详解

    Android 自定义imageview实现图片缩放实例详解 觉得这个自定义的imageview很好用 性能不错  所以拿出来分享给大家  因为不会做gif图  所以项目效果 就不好贴出来了  把代码贴出来 1.项目结构图 2.Compat.class package com.suo.image; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.view.View; pu

  • Android实现相册中图片上传或下载

    本文实例为大家分享了Android实现相册中图片上传或下载的具体代码,供大家参考,具体内容如下 目标效果: 打开相册选择一张图片,会显示到上方的ImageView中并存储到Bmob中,存储后进入Bmob后台,复制刚才添加的数据的objectId,粘贴到代码指定出,然后运行,点击下载会在下方的ImageView显示刚才上传的图片,这里的下载是指定objectId,可以进行动态获取objectId进行下载. 1.activity_main.xml页面设置布局. activity_main.xml页面

  • Android 自定义 View 中使用 Spannable的实例详解

    我们都知道 Android 中使用 Spannable 可以实现 TextView 富文本的显示,但是在自定义控件中如何使用 Spannable 绘制不同样式的文字呢? 例如这种效果,标题中的 分数字61 是粗体,分 是常规字体,并且相对于 61 更小些. 第一反应可能是使用 SpannableString.setSpan() 设置 RelativeSizeSpan, 然后在 onDraw() 中进行绘制,事实是这样实现是没有效果的,因为 onDraw() 中只能获取到 SpannableStr

  • Android自定义view实现图片选色器

    简介 本文介绍该自定义view的使用及实现的方法,主要实现以下几个功能: - 选取圆盘选色图片上的颜色,实时监听 - 可设置选色指示图片,跟随触摸位置.指示所选颜色,示例中为白色圆环 - 可自己设置选色图片(目前只支持圆形图片) github链接 使用效果 首先看下使用效果: 使用示例 在项目中导入该库 在工程的 build.gradle中加入: allprojects { repositories { ... maven { url "https://jitpack.io" } }

  • android自定义ImageView仿图片上传示例

    看下效果图 主要看下自定义view 代码 public class ProcessImageView extends ImageView{ private Context context; private Paint paint; private LogUtil log=LogUtil.getInstance(); int progress = 0; private boolean flag; public ProcessImageView(Context context) { super(co

  • Android自定义View圆形图片控件代码详解

    前言 在日常开发中,圆形的图片效果还是很常见的.可以通过给Paint设置Xfermode来实现,这里简单记录如下. 实现 实现圆形效果的核心是PorterDuffXfermode,对于PorterDuffXfermode,这里不展开,可以查询相关资料. 核心代码 //绘制背景 canvas.drawCircle(mSize / 2, mSize / 2, mSize / 2, mPaint); //设置模式为:显示背景层和上层的交集,且显示上层图像 mPaint.setXfermode(new

  • Android自定义View中Paint、Rect、Canvas介绍(一)

    自定义View对于新手而言貌似是一个很复杂的东西.格式,各函数的意义.对于大神经常忘记各函数及一些参数的具体写法及意义,刚好在做一个风车效果,把过程及遇到的问题都写下来 1.如何自定义一个View public class LeafView extends View { private String TAG = "--------LeafView"; public LeafView(Context context, AttributeSet attrs) { super(context

  • Android自定义视图实现手指移动轨迹

    今天看了大神写的关于贝塞尔曲线的博客,就写下了关于手指轨迹的一篇博客, 一.什么是贝塞尔曲线 贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线.一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的.贝塞尔曲线是计算机图形学中相当重要的参数曲线,在一些比较成熟的位图软件中也有贝塞尔曲线工具,如PhotoShop等. 二.贝塞尔曲线公式 三.手

随机推荐