饿了么ui是什么_饿着饿着突然不饿了为什么

饿了么ui是什么_饿着饿着突然不饿了为什么一样都是静态显示view边距以及相关状态,但是!有了UEtool,不仅能看见view的各种属性,你还能动态改!也就是说你不仅能看你还能摸,有了这个工具,我再也不用为了改1,2个dp的边距我再编译运行了!设计同学也能更好调整UI了。 以UETool官方Demo的捕捉控件功能例吧。…

最近看见一个好库github.com/eleme/UEToo…

1.饿了么UETool效果图&&用途

饿了么ui是什么_饿着饿着突然不饿了为什么

自从我把这个工具给我们设计同学安利之后,她们就爱的不要不要的,用过安卓系统开发者选项的同学知道,有一个查看边界的按钮,但是有时候呢,觉得功能不够,因为开发者选项显示边距的和android studio的Layout Inspector 或者DDMS 的uiautomator工具

饿了么ui是什么_饿着饿着突然不饿了为什么

一样都是静态显示view边距以及相关状态,但是!有了UEtool,不仅能看见view的各种属性,你还能动态改!也就是说你不仅能看你还能摸,有了这个工具,我再也不用为了改1,2个dp的边距我再编译运行了!设计同学也能更好调整UI了。

2.饿了么UETool原理初探

以UETool官方Demo的捕捉控件功能例吧。

饿了么ui是什么_饿着饿着突然不饿了为什么

如何快速分析一个我们完全陌生的app呢,那上工具,第一步先看看目前activity是谁

饿了么ui是什么_饿着饿着突然不饿了为什么

adb shell dumpsys window w | findstr mCurrent或者
adb shell dumpsys window w | grep mCurrent 该命令能区分activity和popupwindow (win用findstr mac/linux用 grep)

好目标就是me.ele.uetool.TransparentActivity

第二步,看目标View

饿了么ui是什么_饿着饿着突然不饿了为什么

这就是捕捉控件功能对应的特殊ViewGroup了,它有一个成员变量叫AttrsDialog是一个自定义Dialog,展示的就是View属性列表的RecyclerView,我们重点看它的adapter

  public static class Adapter extends RecyclerView.Adapter {

        private List<Item> items = new ItemArrayList<>();
        private AttrDialogCallback callback;

        public void setAttrDialogCallback(AttrDialogCallback callback) {
            this.callback = callback;
        }

        public void notifyDataSetChanged(Element element) {
            items.clear();
            for (String attrsProvider : UETool.getInstance().getAttrsProvider()) {
                try {
                    IAttrs attrs = (IAttrs) Class.forName(attrsProvider).newInstance();
                    items.addAll(attrs.getAttrs(element));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            notifyDataSetChanged();
        }

好来一个下一个断点,我们跳过复杂的封装逻辑,直接看运行的函数看调用栈

饿了么ui是什么_饿着饿着突然不饿了为什么

这里我们看见了数据源其实就是element,这个element存有一个View成员变量

public class UETCore implements IAttrs {

    @Override
    public List<Item> getAttrs(Element element) {
        List<Item> items = new ArrayList<>();

        View view = element.getView();

        items.add(new SwitchItem("Move", element, SwitchItem.Type.TYPE_MOVE));

        IAttrs iAttrs = AttrsManager.createAttrs(view);
        if (iAttrs != null) {
            items.addAll(iAttrs.getAttrs(element));
        }

        items.add(new TitleItem("COMMON"));
        items.add(new TextItem("Class", view.getClass().getName()));
        items.add(new TextItem("Id", Util.getResId(view)));
        items.add(new TextItem("ResName", Util.getResourceName(view.getResources(), view.getId())));
        items.add(new TextItem("Clickable", Boolean.toString(view.isClickable()).toUpperCase()));
        items.add(new TextItem("Focused", Boolean.toString(view.isFocused()).toUpperCase()));
        items.add(new AddMinusEditItem("Width(dp)", element, EditTextItem.Type.TYPE_WIDTH, px2dip(view.getWidth())));
        items.add(new AddMinusEditItem("Height(dp)", element, EditTextItem.Type.TYPE_HEIGHT, px2dip(view.getHeight())));
        items.add(new TextItem("Alpha", String.valueOf(view.getAlpha())));
        Object background = Util.getBackground(view);
        if (background instanceof String) {
            items.add(new TextItem("Background", (String) background));
        } else if (background instanceof Bitmap) {
            items.add(new BitmapItem("Background", (Bitmap) background));
        }
        items.add(new AddMinusEditItem("PaddingLeft(dp)", element, EditTextItem.Type.TYPE_PADDING_LEFT, px2dip(view.getPaddingLeft())));
        items.add(new AddMinusEditItem("PaddingRight(dp)", element, EditTextItem.Type.TYPE_PADDING_RIGHT, px2dip(view.getPaddingRight())));
        items.add(new AddMinusEditItem("PaddingTop(dp)", element, EditTextItem.Type.TYPE_PADDING_TOP, px2dip(view.getPaddingTop())));
        items.add(new AddMinusEditItem("PaddingBottom(dp)", element, EditTextItem.Type.TYPE_PADDING_BOTTOM, px2dip(view.getPaddingBottom())));

        return items;
    }

有View对象当然dialog显示View各个属性没问题,那么很奇怪,这个view是MainActivity的,这个新开的TransparentActivity是怎么拿到数据源的呢 莫慌,看这个函数栈,注意到EditAttrLayout 类的triggerActionUp方法的element

@Override
        public void triggerActionUp(MotionEvent event) {
            final Element element = getTargetElement(event.getX(), event.getY());
            if (element != null) {
                EditAttrLayout.this.element = element;
                invalidate();
                if (dialog == null) {
                    dialog = new AttrsDialog(getContext());
                    dialog.setAttrDialogCallback(new AttrsDialog.AttrDialogCallback() {
                        @Override
                        public void enableMove() {
                            mode = new MoveMode();
                            dialog.dismiss();
                        }
                    });
                    dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                        @Override
                        public void onDismiss(DialogInterface dialog) {
                            element.reset();
                            invalidate();
                        }
                    });
                }
                dialog.show(element);
            }
        }

好发现关键句getTargetElement(event.getX(), event.getY()); 点进去会跳到父类CollectViewsLayout的getTargetElement方法

 protected Element getTargetElement(float x, float y) {
        Element target = null;
        for (int i = elements.size() - 1; i >= 0; i--) {
            final Element element = elements.get(i);
            if (element.getRect().contains((int) x, (int) y)) {
                if (element != childElement) {
                    childElement = element;
                    parentElement = element;
                } else if (parentElement != null) {
                    parentElement = parentElement.getParentElement();
                }
                target = parentElement;
                break;
            }
        }
        if (target == null) {
            Toast.makeText(getContext(), getResources().getString(R.string.uet_target_element_not_found, x, y), Toast.LENGTH_SHORT).show();
        }
        return target;
    }

element和elements有直接关系再看到elements List<Element> elements怎么来的呢?list数据填充无非2种常用的要么add要么addAll直接command +f或者ctrl + f搜索elements.add就发现了数据源设置的函数

private void traverse(View view) {
        if (UETool.getInstance().getFilterClasses().contains(view.getClass().getName())) return;
        if (view.getAlpha() == 0 || view.getVisibility() != View.VISIBLE) return;
        if (getResources().getString(R.string.uet_disable).equals(view.getTag())) return;
        elements.add(new Element(view));
        if (view instanceof ViewGroup) {
            ViewGroup parent = (ViewGroup) view;
            for (int i = 0; i < parent.getChildCount(); i++) {
                traverse(parent.getChildAt(i));
            }
        }
    }

来搞个断点看调用栈,或者就在element 构造方法下断点就能省掉上面从element到elemnets的分析 来看下图

饿了么ui是什么_饿着饿着突然不饿了为什么

UETool拿到targetActivity也就是MainActivity,然后反射拿到decoreView,然后调用 EditAttrLayout类的父类CollectViewsLayout类traverse方法。

至此按时间顺序总结一下,CollectViewsLayout类的onAttachedToWindow通过反射拿到目标MainActivity的decoreView,去给CollectViewsLayout的成员变量List<Element> elements add包装了decoreView的Element,然后用户也就是我,点了UETool的操作控件按钮,UP事件的时候AttrsDialog的show方法调用adapter.notifyDataSetChanged(element);给Adapter设置被UETCore解开element各种属性的List<Item>作为数据源

好了,原理简单初探到这里。饿了么大神的代码就这么大概摸完了,代码封装的很不错,建议有兴趣的同学可以看看,学习一下。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13625.html

(0)

相关推荐

  • 《包你懂系列》一文讲清楚 MySQL 事务隔离级别和实现原理,开发人员必备知识点

    《包你懂系列》一文讲清楚 MySQL 事务隔离级别和实现原理,开发人员必备知识点经常提到数据库的事务,那你知道数据库还有事务隔离的说法吗,事务隔离还有隔离级别,那什么是事务隔离,隔离级别又是什么呢?本文就帮大家梳理一下。 本文所说的 MySQL 事务都是指在 InnoDB 引擎下,MyISAM 引擎是不支持事务的。 数据库事务指的是一组数据操作,事务内的操…

    2023-04-02
    133
  • mysql添加索引(建表之后)「建议收藏」

    mysql添加索引(建表之后)「建议收藏」一.使用ALTER TABLE语句创建索引 语法如下: 其中包括普通索引、UNIQUE索引和PRIMARY KEY索引3种创建索引的格式,table_name是要增加索引的表名,column_list

    2023-01-25
    163
  • Python Finding List: 搜索引擎优化数据分析利器

    Python Finding List: 搜索引擎优化数据分析利器随着互联网的不断发展,搜索引擎已成为人们获取信息的重要手段。SEO(Search Engine Optimization)优化技术的使用已经成为企业和网站必不可少的一部分。但是如何分析和优化SEO数据呢?Python Finding List是一款强大的Python工具,可以帮助用户从不同的角度进行SEO数据分析和优化。

    2024-01-02
    107
  • Python中elif关键字的用法

    Python中elif关键字的用法Python是一种面向对象、解释型语言,它与其他语言不同的地方在于采用了indentation(缩进)代替了语句结束的分号或者大括号等符号。Python中的if/elif/else也是控制流程中比较重要的关键字,能够帮助程序员控制程序的逻辑,在不同的条件下执行不同的代码。

    2024-02-12
    90
  • 中国学生占领英国私校,比例超40%,形成了“浓厚”的普通话氛围「终于解决」

    中国学生占领英国私校,比例超40%,形成了“浓厚”的普通话氛围「终于解决」文 / 英伦投资客公众号ID:BuyLondon送小孩去英国寄宿学校留学,已经成为当下许多中国中产家庭的教育时尚。然而,近年来,不少英国寄宿学校

    2023-06-26
    137
  • MySQL学习笔记(19):优化数据库对象

    MySQL学习笔记(19):优化数据库对象本文更新于2019-08-18,使用MySQL 5.7,操作系统为Deepin 15.4。 一旦数据库对象设计完毕并投入使用,再进行修改就比较麻烦。 优化表的数据类型 select_statement

    2023-03-22
    147
  • 大数据hadoop入门教程_大数据集成的基本原理

    大数据hadoop入门教程_大数据集成的基本原理一、Hadoop概述 Hadoop是Apache软件基金会下一个开源分布式计算平台,以HDFS(Hadoop Distributed File System)、MapReduce(Hadoop2.0加

    2023-05-11
    142
  • Android—V2签名下多渠道快速打包方案「终于解决」

    Android—V2签名下多渠道快速打包方案「终于解决」笔者是MIUI系统应用组的开发,之前发布APP时只有应用商店这一个渠道,因此只需给应用商店提供一个APK即可。不过最近应用开发了一个外发版本,该版本有广告、push等多个下载渠道,为了统计各渠道的日活、转化率等信息,需要进行多渠道打包,目前腾讯的VasDolly和美团的Wall…

    2023-07-23
    129

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注