How to get the proper bounds of a view after transformation Matrix

后端 未结 1 1925
无人及你
无人及你 2021-02-04 09:15

I have a custom view where I use transformations. So far so good, function like setRotationY(), setScaleX(), setTranslationY() or even

相关标签:
1条回答
  • 2021-02-04 09:40

    When overriding the “getChildStaticTransformation” method of the ViewGroup or even using transformation function like setRotationY(), setScaleX(), setTranslationY(), getMatrix() (available from API 11) you are only affecting the rendering Matrix. As a result your custom Child View will return Bounds “Rects” far from where your child is getting draw. This is not an issue most of the time but when you start to be willing to click on it.. trouble are starting... Here is how I workaround the issue. I’m sure there might be a better ways but as I haven’t found many things on the subject here it is.

    In the ViewGroup Overload:

    public interface Itransformable {
        public void setTransformationMatrix(Matrix trsMatrix);
    }
    
    @Override
    protected boolean getChildStaticTransformation(View child, Transformation t) {
        if (child instanceof Itransformable){   
            t.clear();
            t.setTransformationType(Transformation.TYPE_MATRIX);
            ...
            // Do whatever transformation you want here
            ...
            ((Itransformable)child).setTransformationMatrix(t.getMatrix());
            return true;
        } else {
            return false;
        }
    }
    

    Here is the Child Custom View: Note that I'm not storing directly the Transformation Matrix in the custom view but instead the transformed Rect. If you want to go for storing the matrix (i.e. for later transformation like point...) you might need to clone it as the matrix will get altered in some strange way like it is recycle or something.

    public class MyCustomView extends View implements MyViewGroup.Itransformable{
    
    private Rect mViewRect = null;
    
    public void setTransformationMatrix(Matrix trsMatrix){
        if (trsMatrix!=null){
            RectF rect = new RectF();
            rect.top = 0;
            rect.bottom = (float) this.getHeight(); 
            rect.left = 0; 
            rect.right = (float) this.getWidth();  
    
            trsMatrix.mapRect(rect);
            rect.offset((float) this.getLeft(), (float) this.getTop());
    
            if (mViewRect == null) mViewRect = new Rect();
            rect.round(mViewRect);
        }
    }
    
    public Rect getTransformatedRect() {
        if (mViewRect!=null){
            // OutOfScreen WorkArround - As the view is not Displayed, mViewRect doesn't get updated.
            if(getRight() < 0 || getLeft() > mParentWidth){
                return new Rect(getLeft(),getTop(),getRight(),getBottom());
            } else {
                return mViewRect;
            }
        } else {
            return new Rect(getLeft(),getTop(),getRight(),getBottom());
        }
    }
    
    @Override
    public void getHitRect(Rect outRect){
    
        if (mViewRect == null){
            super.getHitRect(outRect);
        } else {
            outRect.set(getTransformatedRect());
        }
    }
    
    0 讨论(0)
提交回复
热议问题