草庐IT

android - 用 Espresso 点击 EditText 的 drawable 右边

coder 2023-12-09 原文

如何才能点击 EditText 的右侧可绘制对象(查看屏幕截图)?我尝试了几种方法,但总是卡住。

public static Matcher<View> withEditTextDrawable(final int resourceId) {
    return new BoundedMatcher<View, EditText>(EditText.class) {
        @Override
        protected boolean matchesSafely(final EditText editText) {
            // ????

            return false;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("with drawable from resource id: ");
            description.appendValue(resourceId);
        }
    };
}

最佳答案

必须开发这个自定义操作和匹配器来测试我们在某些文本字段右侧丢弃的可绘制对象, 这将在 Espresso 测试中点击 TextView 的任何可绘制对象(左、上、右、下)。

用法:

onView(withId(id)).perform(clickDrawables());

方法:

public static ViewAction clickDrawables()
{
    return new ViewAction()
    {
        @Override
        public Matcher<View> getConstraints()//must be a textview with drawables to do perform
        {
            return allOf(isAssignableFrom(TextView.class), new BoundedMatcher<View, TextView>(TextView.class)
            {
                @Override
                protected boolean matchesSafely(final TextView tv)
                {
                    if(tv.requestFocusFromTouch())//get fpocus so drawables become visible
                        for(Drawable d : tv.getCompoundDrawables())//if the textview has drawables then return a match
                            if(d != null)
                                return true;

                    return false;
                }

                @Override
                public void describeTo(Description description)
                {
                    description.appendText("has drawable");
                }
            });
        }

        @Override
        public String getDescription()
        {
            return "click drawables";
        }

        @Override
        public void perform(final UiController uiController, final View view)
        {
            TextView tv = (TextView)view;
            if(tv != null && tv.requestFocusFromTouch())//get focus so drawables are visible
            {
                Drawable[] drawables = tv.getCompoundDrawables();

                Rect tvLocation = new Rect();
                tv.getHitRect(tvLocation);

                Point[] tvBounds = new Point[4];//find textview bound locations
                tvBounds[0] = new Point(tvLocation.left, tvLocation.centerY());
                tvBounds[1] = new Point(tvLocation.centerX(), tvLocation.top);
                tvBounds[2] = new Point(tvLocation.right, tvLocation.centerY());
                tvBounds[3] = new Point(tvLocation.centerX(), tvLocation.bottom);

                for(int location = 0; location < 4; location++)
                    if(drawables[location] != null)
                    {
                        Rect bounds = drawables[location].getBounds();
                        tvBounds[location].offset(bounds.width() / 2, bounds.height() / 2);//get drawable click location for left, top, right, bottom
                        if(tv.dispatchTouchEvent(MotionEvent.obtain(android.os.SystemClock.uptimeMillis(), android.os.SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, tvBounds[location].x, tvBounds[location].y, 0)))
                            tv.dispatchTouchEvent(MotionEvent.obtain(android.os.SystemClock.uptimeMillis(), android.os.SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, tvBounds[location].x, tvBounds[location].y, 0));
                    }
            }
        }
    };
}



这是我为选择要单击的特定绘图所做的改进:

用法:

onView(withId(id)).perform(new ClickDrawableAction(ClickDrawableAction.Right));

方法:

public static class ClickDrawableAction implements ViewAction
{
    public static final int Left = 0;
    public static final int Top = 1;
    public static final int Right = 2;
    public static final int Bottom = 3;

    @Location
    private final int drawableLocation;

    public ClickDrawableAction(@Location int drawableLocation)
    {
        this.drawableLocation = drawableLocation;
    }

    @Override
    public Matcher<View> getConstraints()
    {
        return allOf(isAssignableFrom(TextView.class), new BoundedMatcher<View, TextView>(TextView.class)
        {
            @Override
            protected boolean matchesSafely(final TextView tv)
            {
                //get focus so drawables are visible and if the textview has a drawable in the position then return a match
                return tv.requestFocusFromTouch() && tv.getCompoundDrawables()[drawableLocation] != null;

            }

            @Override
            public void describeTo(Description description)
            {
                description.appendText("has drawable");
            }
        });
    }

    @Override
    public String getDescription()
    {
        return "click drawable ";
    }

    @Override
    public void perform(final UiController uiController, final View view)
    {
        TextView tv = (TextView)view;//we matched
        if(tv != null && tv.requestFocusFromTouch())//get focus so drawables are visible
        {
            //get the bounds of the drawable image
            Rect drawableBounds = tv.getCompoundDrawables()[drawableLocation].getBounds();

            //calculate the drawable click location for left, top, right, bottom
            final Point[] clickPoint = new Point[4];
            clickPoint[Left] = new Point(tv.getLeft() + (drawableBounds.width() / 2), (int)(tv.getPivotY() + (drawableBounds.height() / 2)));
            clickPoint[Top] = new Point((int)(tv.getPivotX() + (drawableBounds.width() / 2)), tv.getTop() + (drawableBounds.height() / 2));
            clickPoint[Right] = new Point(tv.getRight() + (drawableBounds.width() / 2), (int)(tv.getPivotY() + (drawableBounds.height() / 2)));
            clickPoint[Bottom] = new Point((int)(tv.getPivotX() + (drawableBounds.width() / 2)), tv.getBottom() + (drawableBounds.height() / 2));

            if(tv.dispatchTouchEvent(MotionEvent.obtain(android.os.SystemClock.uptimeMillis(), android.os.SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, clickPoint[drawableLocation].x, clickPoint[drawableLocation].y, 0)))
                tv.dispatchTouchEvent(MotionEvent.obtain(android.os.SystemClock.uptimeMillis(), android.os.SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, clickPoint[drawableLocation].x, clickPoint[drawableLocation].y, 0));
        }
    }

    @IntDef({ Left, Top, Right, Bottom })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Location{}
}

关于android - 用 Espresso 点击 EditText 的 drawable 右边,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33368190/

有关android - 用 Espresso 点击 EditText 的 drawable 右边的更多相关文章

  1. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  2. ruby - Sinatra:点击 URL 时运行 ruby​​ 代码 - 2

    我想在每次访问url/code时运行一个脚本(code.rb)。如何运行脚本?require'sinatra'get'/'do#runthescriptend 最佳答案 要么fork另一个进程:system('rubycode.rb')...或者简单地将脚本加载到当前上下文中:load'code.rb'#*not*require 关于ruby-Sinatra:点击URL时运行ruby​​代码,我们在StackOverflow上找到一个类似的问题: https:

  3. ruby - 难倒点击与 nokogiri 和 Mechanize 的链接 - 2

    也许我做错了,或者还有另一种更有效的方法。这是我的问题:我首先使用nokogiri打开一个html文档并使用其css遍历该文档,直到找到我需要单击的链接。现在我有了链接后,如何使用Mechanize来点击它?根据文档,Mechanize.new返回的对象是字符串或Mechanize::Page::Link对象。我不能使用字符串-因为可能有100个相同的链接-我只想Mechanize点击nokogiri遍历的链接。有什么想法吗? 最佳答案 找到所需的链接节点后,您可以手动创建Mechanize::Page::Link对象,然后单击它:

  4. ruby - Watir-Webdriver 是否支持点击目标为 javascript 的链接? - 2

    我是Ruby和Watir-Webdriver的新手。我有一套用VBScript编写的站点自动化程序,我想将其转换为Ruby/Watir,因为我现在必须支持Firefox。我发现我真的很喜欢Ruby,而且我正在研究Watir,但我已经花了一周时间试图让Webdriver显示我的登录屏幕。该站点以带有“我同意”区域的“警告屏幕”开头。用户点击我同意并显示登录屏幕。我需要单击该区域以显示登录屏幕(这是同一页面,实际上是一个表单,只是隐藏了)。我整天都在用VBScript这样做:objExplorer.Document.GetElementsByTagName("area")(0).click

  5. ruby - 在 ruby​​ 中查找任意正则表达式的最后(最右边)匹配 - 2

    我正在用ruby​​开发一个文本编辑器,我需要使用用户提供的正则表达式模式来支持“查找”功能。这是一个简单(熟悉的)用例:JoeUseriseditingatextfile,andhaspositionedthecursorsomewhereinthemiddleofthefile.Hewantstosearchbackwardsfromthecurrentcursorlocationforthenearestsubstringmatchinganarbitraryregularexpression.我认为这个问题相当于将用户的模式应用于文件中光标位置之前的整个字符串。当然,我可以从文

  6. 前端实现文件上传(点击+拖拽) - 2

    一、简介之前在Vue项目中使用过element的上传组件,实现了点击上传+拖拽上传的两种上传功能。然后我就在想是否可以通过原生的html+js来实现文件的点击上传和拖拽上传,说干就干。首先是点击获取上传文件自然没的说,只需要借助input标签即可,但原生的点击上传按钮,实在是过于简陋,所以我的想法是通过一个div,模拟成上传按钮,然后监听其点击事件,通过input.click()去模拟点击真正的上传元素。然后是拖拽获取上传文件,这个稍有难度,我的想法是通过HTML5新增的drag拖放API+dataTransfer来实现文件的拖拽获取,但是由于是html5新增的,所以可能在某些低版本IE浏览器

  7. Android Studio开发之使用内容组件Content获取通讯信息讲解及实战(附源码 包括添加手机联系人和发短信) - 2

    运行有问题或需要源码请点赞关注收藏后评论区留言一、利用ContentResolver读写联系人在实际开发中,普通App很少会开放数据接口给其他应用访问。内容组件能够派上用场的情况往往是App想要访问系统应用的通讯数据,比如查看联系人,短信,通话记录等等,以及对这些通讯数据及逆行增删改查。首先要给AndroidMaifest.xml中添加响应的权限配置 下面是往手机通讯录添加联系人信息的例子效果如下分成三个步骤先查出联系人的基本信息,然后查询联系人号码,再查询联系人邮箱代码 ContactAddActivity类packagecom.example.chapter07;importandroid

  8. Android 10.0 设置默认launcher后安装另外launcher后默认Launcher失效的功能修复 - 2

    1.前言 在10.0的系统rom定制化开发中,在系统中有多个launcher的时候,会在开机进入launcher的时候弹窗launcher列表,让用户选择进入哪个launcher,这样显得特别的不方便所以产品开发中,要求用RoleManager的相关api来设置默认Launcher,但是在设置完默认Launcher以后,在安装一款Launcher的时候,默认Launcher就会失效,在系统设置的默认应用中Launcher选项就为空,点击home键的时候会弹出默认Launcher列表,让选择进入哪个默认Launcher.所以需要从安装Launcher的流程来分析相关的设置。来解决问题设置默认La

  9. ruby - 在 cucumber 中使用 capybara 点击图像 - 2

    我试图用Capybara单击一张图片进行Cucumber测试,但找不到让Capybara将图片视为链接的方法。我的图片代码是:link_to(image_tag('ico_edit_16.png',alt:'Edit',class:'icon16',title:"Edit#{qualification.title}"),edit_qualification_path(qualification))显示为在html中,我一直无法找到使用capybara点击图片的好方法。有什么建议吗? 最佳答案 这应该有效:find('img.icon

  10. ruby-on-rails - Rails number_to_currency 删除小数点右边的尾随零 - 2

    我有一个动态生成的表格,它乘以价格*数量。部分价格以美分计算。例如如果某件商品的价格是0.0375,我可以在我的表格中将其显示为number_to_currency(0.0375,:precision=>4)=>$0.0375但是我得到的价格是标准的2位小数的数量number_to_currency(33.95,:precision=>4)=>$39.9500我需要一种方法来去除十进制值的尾随零。请记住,输出位于Model.eachblock中,因此我不确定是否可以有条件地修改精度参数。 最佳答案 尝试指定strip_insigni

随机推荐