Android 遍历界面所有的View

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。

专注于分享各领域原创系列文章 ,擅长java后端、移动开发、商业变现、人工智能等,希望大家多多支持。

目录

一、导读

我们继续总结学习,温故知新。

二、概览

本文讲述如何遍历获取页面中所有的view,并输出对应的id,textview文本内容,imageview实际大小及设置的图片大小。

可用于检测android应用中的大图。

三、实践

不多说,直接上代码,

图片大小检测思路。

java 复制代码
    fun checkBitmapFromView(){
        //1、遍历activity中的各个View控件
        //2、获取View控件加载的Bitmap
        //3、对比Bitmap宽高与View宽高
    }

示例代码:

遍历获取所有的view,并输出相应的信息

java 复制代码
    List<View> viewList=new ArrayList<>();
    @Override
    protected void onResume() {
        super.onResume();
        logoIcon.postDelayed(new Runnable() {
            @Override
            public void run() {
                getAllViews((ViewGroup) getWindow().getDecorView());
                for (View view: viewList) {

                    if(view instanceof TextView) {
                        Log.d("xyz", view.toString());
                        Log.d("xyz", ((TextView)view).getText().toString());

                    } else if(view instanceof ImageView) {
                        Log.d("xyz", view.toString());
                        checkBitmap(view, ((ImageView)view).getDrawable());
                    } else {
                        Log.d("xyz", view.toString());
                    }
                }
            }
        }, 3000);
    }
java 复制代码
    //获取所有的子view,我们这里只保存imageview及textview,用于测试
    private List<View> getAllViews(ViewGroup viewGroup){
        for(int i=0;i< viewGroup.getChildCount(); i++){
            View view = viewGroup.getChildAt(i);
            if(view instanceof ViewGroup) {
                getAllViews((ViewGroup) view);
            } else {
                if(view instanceof ImageView || view instanceof TextView) {
                    viewList.add(view);
                }
                if(view.getVisibility() == View.VISIBLE) {
                }
            }
        }
        return viewList;
    }

ImageView大小检测

java 复制代码
    private void checkBitmap(Object thiz, Drawable drawable) {
        if (drawable instanceof BitmapDrawable && thiz instanceof View) {
            final Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();

            final View view = (View) thiz;
            int width = view.getWidth();
            int height = view.getHeight();

            if (bitmap != null) {
                if (width > 0 && height > 0) {
                    // 图标宽高都大于view带下的2倍以上,则警告
                    if (bitmap.getWidth() >= (width << 1)
                            && bitmap.getHeight() >= (height << 1)) {
//                        warn(bitmap.getWidth(), bitmap.getHeight(), width, height, new RuntimeException("Bitmap size too large"));
                    }
                    warn(bitmap.getWidth(), bitmap.getHeight(), width, height, new RuntimeException("log"));
                } else {
                    final Throwable stackTrace = new RuntimeException();
                    view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                        @Override
                        public boolean onPreDraw() {
                            int w = view.getWidth();
                            int h = view.getHeight();
                            if (w > 0 && h > 0) {
                                if (bitmap.getWidth() >= (w << 1)
                                        && bitmap.getHeight() >= (h << 1)) {
//                                    warn(bitmap.getWidth(), bitmap.getHeight(), w, h, stackTrace);
                                }
                                warn(bitmap.getWidth(), bitmap.getHeight(), w, h, stackTrace);
                                view.getViewTreeObserver().removeOnPreDrawListener(this);
                            }
                            return true;
                        }
                    });
                }
            } else {

                warn(bitmap.getWidth(), bitmap.getHeight(), width, height, new RuntimeException("bitmap null"));
            }
        }
    }

    private void warn(int bitmapWidth, int bitmapHeight, int viewWidth, int viewHeight, Throwable t) {
        String warnInfo = new StringBuilder("Bitmap info: ")
                .append("\n real size: (").append(bitmapWidth).append(',').append(bitmapHeight).append(')')
                .append("\n desired size: (").append(viewWidth).append(',').append(viewHeight).append(')')
                .append("\n call stack trace: \n").append(Log.getStackTraceString(t)).append('\n')
                .toString();

        Log.d("xyz", warnInfo);
    }

我们看下log输出

java 复制代码
com.xxx.xxx.xxx.ImageViewFor{e292c7e VFED..C.. ........ 540,1348-900,1528 #7f0a024e app:id/bt_phone}
2023-08-23 18:28:47.956 12556-12556 xyz                com.xxx.xxx                      D  Bitmap info: 
         real size: (144,144)
         desired size: (360,180)
         call stack trace: 
        java.lang.RuntimeException: log
            at com.xxx.xxx.ui.LoginActivity.checkBitmap(LoginActivity.java:235)
            at com.xxx.xxx.ui.LoginActivity.access$100(LoginActivity.java:79)
            at com.xxx.xxx.ui.LoginActivity$2.run(LoginActivity.java:193)
            at android.os.Handler.handleCallback(Handler.java:900)
            at android.os.Handler.dispatchMessage(Handler.java:103)
            at android.os.Looper.loop(Looper.java:219)
            at android.app.ActivityThread.main(ActivityThread.java:8673)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)

四、 推荐阅读

Java 专栏

SQL 专栏

数据结构与算法

Android学习专栏

相关推荐
chjif4 分钟前
Android 设备管控开发实战:企业受控终端的 DNS 域名策略实现
android·华为·harmonyos
c238562 小时前
MySQL 基础用法(下):查询进阶与核心特性
android·c语言·c++·mysql
码匠许师傅2 小时前
【C++ 面试真题】 C++ 中的 static 有什么作用?
c++·面试
math_hongfan2 小时前
鸿蒙Agent高级技能自定义开发:自定义意图服务/能力注册/Agent技能编排/服务插件开发实战
android·学习·华为·harmonyos·鸿蒙
胡萝卜术3 小时前
声明式与命令式的边界:从鉴权路由守卫到 useRef 的引用哲学
前端·javascript·面试
黄敬峰3 小时前
# React 自定义 Hook 从入门到实战——用 useTodos 和 useTheme 彻底搞懂封装思维 > 刚开始学 React Hooks 的时候,
面试
2501_915106323 小时前
iOS 证书类型及作用说明 账号证书与签名配置的完整解读
android·ios·小程序·https·uni-app·iphone·webview
九皇叔叔3 小时前
RHEL9 安装 MySQL 8.4.11.LTS 版本
android·mysql·adb
海兰4 小时前
【数据库】tdsql(MySQL )的事务隔离级别
android·数据库·mysql
哆啦A梦z4 小时前
Android BLE 实战:从小米手环 7 踩坑到完整连接框架
android