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

从广义的角度来看,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图片内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Android自定义视图中图片的处理的更多相关文章

  1. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  2. html5 canvas合成海报所遇问题及解决方案总结

    这篇文章主要介绍了html5 canvas合成海报所遇问题及解决方案总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  4. HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题

    HTML5在微信内置浏览器下,在右上角菜单的调整字体导致页面显示错乱的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  5. ios – containerURLForSecurityApplicationGroupIdentifier:在iPhone和Watch模拟器上给出不同的结果

    我使用默认的XCode模板创建了一个WatchKit应用程序.我向iOSTarget,WatchkitAppTarget和WatchkitAppExtensionTarget添加了应用程序组权利.(这是应用程序组名称:group.com.lombax.fiveminutes)然后,我尝试使用iOSApp和WatchKitExtension访问共享文件夹URL:延期:iOS应用:但是,测试NSURL

  6. Ionic – Splash Screen适用于iOS,但不适用于Android

    我有一个离子应用程序,其中使用CLI命令离子资源生成的启动画面和图标iOS版本与正在渲染的启动画面完美配合,但在Android版本中,只有在加载应用程序时才会显示白屏.我检查了config.xml文件,所有路径看起来都是正确的,生成的图像出现在相应的文件夹中.(我使用了splash.psd模板来生成它们.我错过了什么?这是config.xml文件供参考,我觉得我在这里做错了–解决方法在config.xml中添加以下键:它对我有用!

  7. ios – 无法启动iPhone模拟器

    /Library/Developer/CoreSimulator/Devices/530A44CB-5978-4926-9E91-E9DBD5BFB105/data/Containers/Bundle/Application/07612A5C-659D-4C04-ACD3-D211D2830E17/ProductName.app/ProductName然后,如果您在Xcode构建设置中选择标准体系结构并再次构建和运行,则会产生以下结果:dyld:lazysymbolbindingFailed:Symbol

  8. Xamarin iOS图像在Grid内部重叠

    heyo,所以在Xamarin我有一个使用并在其中包含一对,所有这些都包含在内.这在Xamarin.Android中看起来完全没问题,但是在Xamarin.iOS中,图像与标签重叠.我不确定它的区别是什么–为什么它在Xamarin.Android中看起来不错但在iOS中它的全部都不稳定?

  9. 在iOS上向后播放HTML5视频

    我试图在iPad上反向播放HTML5视频.HTML5元素包括一个名为playbackRate的属性,它允许以更快或更慢的速率或相反的方式播放视频.根据Apple’sdocumentation,iOS不支持此属性.通过每秒多次设置currentTime属性,可以反复播放,而无需使用playbackRate.这种方法适用于桌面Safari,但似乎在iOS设备上的搜索限制为每秒1次更新–在我的情况下太慢了.有没有办法在iOS设备上向后播放HTML5视频?解决方法iOS6Safari现在支持playbackRat

  10. 使用 Swift 语言编写 Android 应用入门

    Swift标准库可以编译安卓armv7的内核,这使得可以在安卓移动设备上执行Swift语句代码。做梦,虽然Swift编译器可以胜任在安卓设备上编译Swift代码并运行。这需要的不仅仅是用Swift标准库编写一个APP,更多的是你需要一些框架来搭建你的应用用户界面,以上这些Swift标准库不能提供。简单来说,构建在安卓设备上使用的Swiftstdlib需要libiconv和libicu。通过命令行执行以下命令:gitclonegit@github.com:SwiftAndroid/libiconv-libi

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部