热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

requestLayout()方法引发的一系列问题

requestLayout()引起的问题网上有大量写的很深入的requestLayout()源码分析的文章。故这里不再写了,只做一个实际情况下遇到的问题的分析。起因:自定义了一个C
requestLayout()引起的问题

网上有大量写的很深入的requestLayout()源码分析的文章。故这里不再写了,只做一个实际情况下遇到的问题的分析。

起因:

自定义了一个CircleImageView,功能是调用setImage(Bitmap bitmap)后可以将图片以圆形加载。

本以为直接在setImage(Bitmap)的结尾直接调用requestLayout()即可。

这里从两个方面写:

xml中定义为wrap_content

LayoutParamswrap_content时,我处理的逻辑是:在onMeasure()中根据宽高的MeasureSpec是否等于MeasureSpec.AT_MOST,如果等于,那么在第一次绘制的时候,setMeasureDimension()都设置成0,而当调用了setBitmap()时,获取图片的宽高并保存,然后调用requestLayout(),此举引起onMeasure(),那么在此处将图片的宽高设置到setMeasureDimension()中,而整体的View的测量大小就是图片大小了。

此时我的onMeasuresetBitmap长这样:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d(TAG, "onMeasure: ");
int ws = MeasureSpec.getSize(widthMeasureSpec);
int hs = MeasureSpec.getSize(heightMeasureSpec);
int wm = MeasureSpec.getMode(widthMeasureSpec);
int hm = MeasureSpec.getMode(heightMeasureSpec);
//如果子view是wrap_content,那么view就设置成bitmap的大小。
if (wm == MeasureSpec.AT_MOST) {
ws = bitmapW;
}
if (hm == MeasureSpec.AT_MOST) {
hs = bitmapH;
}
int resultW = MeasureSpec.makeMeasureSpec(ws, wm);
int resultH = MeasureSpec.makeMeasureSpec(hs, hm);
super.onMeasure(resultW, resultH);
}
public void setImage(Bitmap bitmap) {
mBitmap = bitmap;
bitmapH = mBitmap.getHeight();
bitmapW = mBitmap.getWidth();
requestLayout();//最后要调用一个requestLayout,引起onMeasure()和onLayout()。
}

大小不同的两张图片

此时为这个CircleImageView准备了两张分辨率不同的图片,点击按钮A加载图片A,点击按钮B加载图片B。

点击情况:

  1. 由显示A的情况下加载B,或者显示B的情况下加载A,或者从没有图片情况下点击加载A或B,分别引起了onMeasure(),onSizeChanged(),onLayout(),onDraw回调。成功地在onDraw重新drawBitmap()切换了图片。
  2. 当在A图片下点击按钮A,或者在B图片下点击按钮B。只引起了onMeasure()onLayout()回调。这里少了一个onSizeChanged()很好理解,因为在该情况下,setMeasureDimesion()传入的值和上一次一样,View中可以很容易通过这种判断而跳过onSizeChanged()回调,而至于为什么onDraw()回调没有引起,这点我也很疑惑。

大小相同的两张图片

此时我又准备了两张大小相同的图片。操作和上述一样。

点击情况:

  1. 从没有图片的情况下点击加载图片A:onMeasure(),onSizeChanged(),onLayout(),onDraw
  2. 从图片A点击加载图片B:加载失败,图片仍然停留在图片A,此时的回调是:onMeasure()和`onLayout()`
  3. 图片A点击加载图片A: 同2。

推论:(在wrap_content情况下)

  1. requestLayout()调用时,一定会引起onMeasure()onLayout()
  2. requestLayout()调用时,如果没有在setMeasureDimension()中传入和上次不同的测量值的话,一定不会引起onSizeChanged()onDraw()onSizeChanged()不被调用的原因很容易在onLayout()的源码中找到答案,而onDraw()不引起回调的原因目前还不明白。

xml中定义为精确值

  1. 情况:此时图片直接无法加载。仅仅在第一次实例化CircleImageView的时候会依次调用onMeasure(),onSizeChanged(),onLayout(),onDraw,伺候每一次调用setImage()都只会引起onMeasure()onLayout()

  2. 原因:因为在requestLayout()调用后,因为此时的测量模式是EXACTLY,因此setMeasuredDimension()中传入的值永远不变,永远都是xml中定义的那个精确值。而上文的推论中指出,setMeasuredDimension()传入的值等于原本的测量值的话,直接引起onSizeChanged()onDraw()无法调用。

结论

  1. 上文中的推论
  2. 不能依赖requestLayout来引起onDraw()回调,如果百分之百确定要绘制,直接调用invalidate()postInvalidate(),他们只会引起onDraw()的回调。
  3. CircleImageView源码:https://github.com/William619499149/anddroid-little-bubble/blob/master/CircleImageView.java

推荐阅读
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 本文介绍了一款名为TimeSelector的Android日期时间选择器,采用了Material Design风格,可以在Android Studio中通过gradle添加依赖来使用,也可以在Eclipse中下载源码使用。文章详细介绍了TimeSelector的构造方法和参数说明,以及如何使用回调函数来处理选取时间后的操作。同时还提供了示例代码和可选的起始时间和结束时间设置。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
  • 突破MIUI14限制,自定义胶囊图标、大图标样式,支持任意APP
    本文介绍了如何突破MIUI14的限制,实现自定义胶囊图标和大图标样式,并支持任意APP。需要一定的动手能力和主题设计师账号权限或者会主题pojie。详细步骤包括应用包名获取、素材制作和封包获取等。 ... [详细]
author-avatar
呵呵哒
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有