Can I increase a buttons onclick-area programmatically?

后端 未结 8 1984
孤独总比滥情好
孤独总比滥情好 2021-02-01 16:34

Sometimes I have a button in my UI that it is so small that it is difficult to click. My solution so far has been to add a transparent border around the button in photoshop. Jus

8条回答
  •  [愿得一人]
    2021-02-01 16:49

    What I did is not the recommended way and very few will find it useful.

    For me it was the best solution, because TouchDelegate did not worked in all View hierarchy scenarios.

    The solution is based on overriding the hidden

    View class
    public boolean pointInView(float localX, float localY, float slop)
    

    Here is the code:

       public boolean pointInView(float localX, float localY, float slop) {
        boolean res = ae_pointInView(localX, localY, slop, slop);
        if(!res) {
            if(viewIsClickableButToSmall(this)) {
                //our view is clickable itself
                float newSlopX = Math.max(slop, slop + minTouchableViewWidth - this.getWidth());
                float newSlopY = Math.max(slop, slop + minTouchableViewHeight - this.getHeight());
                if(ae_pointInView(localX, localY, newSlopX, newSlopY)) {
                    return true;
                }
            }
    
            //the point is outside our view, now check for views with increased tap area that may extent beyond it
            int childCount = getChildCount();
            for(int i = 0; i < childCount;i++) {
                View child = getChildAt(i);
                if(child instanceof MyViewGroup) {
                    //this is our container that may also contain views with increased tap area
    
                    float[] newPoint = ae_transformPointToViewLocal(localX, localY, child);
                    if(((MyViewGroup) child).pointInView(newPoint[0], newPoint[1], slop)) {
                        return true;
                    }
                }
                else {
                    if(viewIsClickableButToSmall(child)) {
                        float[] newPoint = ae_transformPointToViewLocal(localX, localY, child);
                        float newSlopX = Math.max(slop, slop + minTouchableViewWidth - this.getWidth());
                        float newSlopY = Math.max(slop, slop + minTouchableViewHeight - this.getHeight());
                        if(ae_pointInView(newPoint[0], newPoint[1], newSlopX, newSlopY)) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        else
            return true;
    }
    
    private int minTouchableViewHeight, minTouchableViewWidth;
    private boolean viewIsClickableButToSmall(View view)
    {
        minTouchableViewHeight = GlobalHelper.dipToDevicePixels(40);
        minTouchableViewWidth = GlobalHelper.dipToDevicePixels(40);
    
        return (view.getHeight() < minTouchableViewHeight || view.getWidth() < minTouchableViewWidth) && view.hasOnClickListeners();
    }
    
    public boolean ae_pointInView(float localX, float localY, float slopX, float slopY) {
        boolean res = localX >= -slopX && localY >= -slopY && localX < ((getRight() - getLeft()) + slopX) &&
                localY < ((getBottom() - getTop()) + slopY);
        return res;
    }
    
    private float[] tempPoint;
    public float[] ae_transformPointToViewLocal(float x, float y, View child) {
        if(tempPoint == null) {
            tempPoint = new float[2];
        }
        tempPoint[0] = x + getScrollX() - child.getLeft();
        tempPoint[1] = y + getScrollY() - child.getTop();
    
        return tempPoint;
    }
    

提交回复
热议问题