在android中缩放、平移和旋转带边框的ImageView

在android中缩放、平移和旋转带边框的ImageView,android,rotation,imageview,translate-animation,custom-widgets,Android,Rotation,Imageview,Translate Animation,Custom Widgets,有人知道如何让imageview可以通过按钮控制进行缩放、平移和旋转吗 我已经尝试使用matrix翻译和缩放imageview,但当它有2个imageview时,我无法实现它,并且仍然不知道如何在图像视图中添加边框和按钮。我完全理解您在实现小部件的自定义视图时所面临的复杂性。当我尝试创建自定义小部件时,我遇到了类似的挑战。虽然我必须解决透明性的问题,并在小部件设计中实现平滑角度。请更深入地了解我的想法。这可能会对您有所帮助。请添加这个扩展了框架布局的类;旋转、缩放和平移在图像上有边框,在左上角

有人知道如何让imageview可以通过按钮控制进行缩放、平移和旋转吗


我已经尝试使用matrix翻译和缩放imageview,但当它有2个imageview时,我无法实现它,并且仍然不知道如何在图像视图中添加边框和按钮。

我完全理解您在实现小部件的自定义视图时所面临的复杂性。当我尝试创建自定义小部件时,我遇到了类似的挑战。虽然我必须解决透明性的问题,并在小部件设计中实现平滑角度。请更深入地了解我的想法。这可能会对您有所帮助。

请添加这个扩展了
框架布局的类;旋转、缩放和平移在图像上有边框,在左上角有删除按钮

public static final String TAG = "Sticker Drag";

public static BorderView iv_border;
public static ImageView iv_scale;
public static ImageView iv_delete;
public static ImageView iv_flip;

// For scalling
private float this_orgX = -1, this_orgY = -1;
private float scale_orgX = -1, scale_orgY = -1;
private double scale_orgWidth = -1, scale_orgHeight = -1;
// For rotating
private float rotate_orgX = -1, rotate_orgY = -1, rotate_newX = -1, rotate_newY = -1;
// For moving
private float move_orgX =-1, move_orgY = -1;

private double centerX, centerY;

private final static int BUTTON_SIZE_DP = 30;
private final static int SELF_SIZE_DP = 100;



public StickerView(Context context) {
    super(context);
    init(context);
}

public StickerView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public StickerView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
}

private void init(Context context){
    this.iv_border = new BorderView(context);
    this.iv_scale = new ImageView(context);
    this.iv_delete = new ImageView(context);
    this.iv_flip = new ImageView(context);

    this.iv_scale.setImageResource(R.drawable.zoominout);
    this.iv_delete.setImageResource(R.drawable.remove);
    this.iv_flip.setImageResource(R.drawable.flip);

    this.setTag("DraggableViewGroup");
    this.iv_border.setTag("iv_border");
    this.iv_scale.setTag("iv_scale");
    this.iv_delete.setTag("iv_delete");
    this.iv_flip.setTag("iv_flip");

    int margin = convertDpToPixel(BUTTON_SIZE_DP, getContext())/2;
    int size = convertDpToPixel(SELF_SIZE_DP, getContext());

    LayoutParams this_params =
            new LayoutParams(
                    size,
                    size
            );
    this_params.gravity = Gravity.CENTER;

    LayoutParams iv_main_params =
            new LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
            );
    iv_main_params.setMargins(margin,margin,margin,margin);

    LayoutParams iv_border_params =
            new LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
            );
    iv_border_params.setMargins(margin,margin,margin,margin);

    LayoutParams iv_scale_params =
            new LayoutParams(
                    convertDpToPixel(BUTTON_SIZE_DP, getContext()),
                    convertDpToPixel(BUTTON_SIZE_DP, getContext())
            );
    iv_scale_params.gravity = Gravity.BOTTOM | Gravity.RIGHT;

    LayoutParams iv_delete_params =
            new LayoutParams(
                    convertDpToPixel(BUTTON_SIZE_DP, getContext()),
                    convertDpToPixel(BUTTON_SIZE_DP, getContext())
            );
    iv_delete_params.gravity = Gravity.TOP | Gravity.RIGHT;

    LayoutParams iv_flip_params =
            new LayoutParams(
                    convertDpToPixel(BUTTON_SIZE_DP, getContext()),
                    convertDpToPixel(BUTTON_SIZE_DP, getContext())
            );
    iv_flip_params.gravity = Gravity.TOP | Gravity.LEFT;

    this.setLayoutParams(this_params);
    this.addView(getMainView(), iv_main_params);
    this.addView(iv_border, iv_border_params);
    this.addView(iv_scale, iv_scale_params);
    this.addView(iv_delete, iv_delete_params);
    this.addView(iv_flip, iv_flip_params);
    this.setOnTouchListener(mTouchListener);
    this.iv_scale.setOnTouchListener(mTouchListener);
    this.iv_delete.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            if(StickerView.this.getParent()!=null){
                ViewGroup myCanvas = ((ViewGroup)StickerView.this.getParent());
                myCanvas.removeView(StickerView.this);
            }
        }
    });
    this.iv_flip.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View view) {
            Log.v(TAG, "flip the view");

            /*View mainView = getMainView();
            mainView.setRotationY(mainView.getRotationY() == -180f? 0f: -180f);
            mainView.invalidate();
            requestLayout();*/
            iv_border.setVisibility(View.INVISIBLE);
            iv_scale.setVisibility(View.INVISIBLE);
            iv_delete.setVisibility(View.INVISIBLE);
            iv_flip.setVisibility(View.INVISIBLE);

        }
    });
}

public boolean isFlip(){
    return getMainView().getRotationY() == -180f;
}

protected abstract View getMainView();

private OnTouchListener mTouchListener = new OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent event) {

        if(view.getTag().equals("DraggableViewGroup")) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    Log.v(TAG, "sticker view action down");
                    move_orgX = event.getRawX();
                    move_orgY = event.getRawY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    Log.v(TAG, "sticker view action move");
                    float offsetX = event.getRawX() - move_orgX;
                    float offsetY = event.getRawY() - move_orgY;
                    StickerView.this.setX(StickerView.this.getX()+offsetX);
                    StickerView.this.setY(StickerView.this.getY() + offsetY);
                    move_orgX = event.getRawX();
                    move_orgY = event.getRawY();
                    break;
                case MotionEvent.ACTION_UP:
                    Log.v(TAG, "sticker view action up");
                    setControlItemsHidden(false);
                    break;
                default:
                    Log.e(TAG,"________Touch_______");
                    break;
            }
        }else if(view.getTag().equals("iv_scale")){
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    Log.v(TAG, "iv_scale action down");

                    this_orgX = StickerView.this.getX();
                    this_orgY = StickerView.this.getY();

                    scale_orgX = event.getRawX();
                    scale_orgY = event.getRawY();
                    scale_orgWidth = StickerView.this.getLayoutParams().width;
                    scale_orgHeight = StickerView.this.getLayoutParams().height;

                    rotate_orgX = event.getRawX();
                    rotate_orgY = event.getRawY();

                    centerX = StickerView.this.getX()+
                            ((View)StickerView.this.getParent()).getX()+
                            (float)StickerView.this.getWidth()/2;


                    //double statusBarHeight = Math.ceil(25 * getContext().getResources().getDisplayMetrics().density);
                    int result = 0;
                    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
                    if (resourceId > 0) {
                        result = getResources().getDimensionPixelSize(resourceId);
                    }
                    double statusBarHeight = result;
                    centerY = StickerView.this.getY()+
                            ((View)StickerView.this.getParent()).getY()+
                            statusBarHeight+
                            (float)StickerView.this.getHeight()/2;

                    break;
                case MotionEvent.ACTION_MOVE:
                    Log.v(TAG, "iv_scale action move");

                    rotate_newX = event.getRawX();
                    rotate_newY = event.getRawY();

                    double angle_diff = Math.abs(
                            Math.atan2(event.getRawY() - scale_orgY , event.getRawX() - scale_orgX)
                                    - Math.atan2(scale_orgY - centerY, scale_orgX - centerX))*180/ Math.PI;

                    Log.v(TAG, "angle_diff: "+angle_diff);

                    double length1 = getLength(centerX, centerY, scale_orgX, scale_orgY);
                    double length2 = getLength(centerX, centerY, event.getRawX(), event.getRawY());

                    int size = convertDpToPixel(SELF_SIZE_DP, getContext());
                    if(length2 > length1
                            && (angle_diff < 25 || Math.abs(angle_diff-180)<25)
                            ) {
                        //scale up
                        double offsetX = Math.abs(event.getRawX() - scale_orgX);
                        double offsetY = Math.abs(event.getRawY() - scale_orgY);
                        double offset = Math.max(offsetX, offsetY);
                        offset = Math.round(offset);
                        StickerView.this.getLayoutParams().width += offset;
                        StickerView.this.getLayoutParams().height += offset;
                        onScaling(true);
                        //DraggableViewGroup.this.setX((float) (getX() - offset / 2));
                        //DraggableViewGroup.this.setY((float) (getY() - offset / 2));
                    }else if(length2 < length1
                            && (angle_diff < 25 || Math.abs(angle_diff-180)<25)
                            && StickerView.this.getLayoutParams().width > size/2
                            && StickerView.this.getLayoutParams().height > size/2) {
                        //scale down
                        double offsetX = Math.abs(event.getRawX() - scale_orgX);
                        double offsetY = Math.abs(event.getRawY() - scale_orgY);
                        double offset = Math.max(offsetX, offsetY);
                        offset = Math.round(offset);
                        StickerView.this.getLayoutParams().width -= offset;
                        StickerView.this.getLayoutParams().height -= offset;
                        onScaling(false);
                    }

                    //rotate

                    double angle = Math.atan2(event.getRawY() - centerY, event.getRawX() - centerX) * 180 / Math.PI;
                    Log.v(TAG, "log angle: " + angle);

                    //setRotation((float) angle - 45);
                    setRotation((float) angle - 45);
                    Log.v(TAG, "getRotation(): " + getRotation());

                    onRotating();

                    rotate_orgX = rotate_newX;
                    rotate_orgY = rotate_newY;

                    scale_orgX = event.getRawX();
                    scale_orgY = event.getRawY();

                    postInvalidate();
                    requestLayout();
                    break;
                case MotionEvent.ACTION_UP:
                    Log.v(TAG, "iv_scale action up");
                    break;
            }
        }else{
            Log.e("OnTouch","___________");
           // StickerView.setControlItemsHidden(false);
        }
        return true;
    }
};

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
}

private double getLength(double x1, double y1, double x2, double y2){
    return Math.sqrt(Math.pow(y2-y1, 2)+ Math.pow(x2-x1, 2));
}

private float[] getRelativePos(float absX, float absY){
    Log.v("ken", "getRelativePos getX:"+((View)this.getParent()).getX());
    Log.v("ken", "getRelativePos getY:"+((View)this.getParent()).getY());
    float [] pos = new float[]{
            absX-((View)this.getParent()).getX(),
            absY-((View)this.getParent()).getY()
    };
    Log.v(TAG, "getRelativePos absY:"+absY);
    Log.v(TAG, "getRelativePos relativeY:"+pos[1]);
    return pos;
}

public static void setControlItemsHidden(boolean isHidden){
    if(isHidden) {
        iv_border.setVisibility(View.INVISIBLE);
        iv_scale.setVisibility(View.INVISIBLE);
        iv_delete.setVisibility(View.INVISIBLE);
        iv_flip.setVisibility(View.INVISIBLE);
    }else{
        iv_border.setVisibility(View.VISIBLE);
        iv_scale.setVisibility(View.VISIBLE);
        iv_delete.setVisibility(View.VISIBLE);
        iv_flip.setVisibility(View.VISIBLE);
    }
}

protected View getImageViewFlip(){
    return iv_flip;
}

protected void onScaling(boolean scaleUp){}

protected void onRotating(){}

private class BorderView extends View {

    public BorderView(Context context) {
        super(context);
    }

    public BorderView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public BorderView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // Draw sticker border

        LayoutParams params = (LayoutParams)this.getLayoutParams();

        Log.v(TAG,"params.leftMargin: "+params.leftMargin);

        Rect border = new Rect();
        border.left = (int)this.getLeft()-params.leftMargin;
        border.top = (int)this.getTop()-params.topMargin;
        border.right = (int)this.getRight()-params.rightMargin;
        border.bottom = (int)this.getBottom()-params.bottomMargin;
        Paint borderPaint = new Paint();
        borderPaint.setStrokeWidth(6);
        borderPaint.setColor(Color.WHITE);
        borderPaint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(border, borderPaint);

    }
}

private static int convertDpToPixel(float dp, Context context){
    Resources resources = context.getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return (int)px;
}
public static final String TAG=“粘贴拖动”;
公共静态边界视图iv_边界;
公共静态图像视图iv_标度;
公共静态图像视图iv_删除;
公共静态图像视图iv_翻转;
//鳞片
私有浮动this_orgX=-1,this_orgY=-1;
私有浮动比例_orgX=-1,比例_orgY=-1;
专用双刻度或宽度=-1,刻度或高度=-1;
//用于旋转
私有浮点rotate\u orgX=-1,rotate\u orgY=-1,rotate\u newX=-1,rotate\u newY=-1;
//搬家
私有浮动move_orgX=-1,move_orgY=-1;
私人双centerX、centerY;
专用最终静态int按钮大小DP=30;
专用最终静态int自身大小DP=100;
公共视图(上下文){
超级(上下文);
init(上下文);
}
公共标签视图(上下文、属性集属性){
超级(上下文,attrs);
init(上下文);
}
公共标签视图(上下文上下文、属性集属性、int-defStyle){
超级(上下文、属性、定义样式);
init(上下文);
}
私有void init(上下文){
this.iv_border=新边界视图(上下文);
此.iv_比例=新图像视图(上下文);
this.iv_delete=新图像视图(上下文);
this.iv_flip=新图像视图(上下文);
这个.iv_刻度.setImageResource(R.drawable.zoominout);
这个.iv_delete.setImageResource(R.drawable.remove);
这个.iv_flip.setImageResource(R.drawable.flip);
此.setTag(“DragableViewGroup”);
此.iv_border.setTag(“iv_border”);
此.iv_刻度.setTag(“iv_刻度”);
此.iv_delete.setTag(“iv_delete”);
这个.iv_flip.setTag(“iv_flip”);
int margin=convertDpToPixel(按钮大小,getContext())/2;
int size=convertDpToPixel(SELF_size_DP,getContext());
LayoutParams此参数=
新布局参数(
大小,
大小
);
此参数重力=重心;
布局参数iv_主参数=
新布局参数(
ViewGroup.LayoutParams.MATCH_父级,
ViewGroup.LayoutParams.MATCH_父级
);
iv_主要参数设置页边距(页边距、页边距、页边距、页边距);
布局参数iv_边界_参数=
新布局参数(
ViewGroup.LayoutParams.MATCH_父级,
ViewGroup.LayoutParams.MATCH_父级
);
iv_border_参数设置边距(边距、边距、边距、边距);
布局参数iv_比例参数=
新布局参数(
convertDpToPixel(按钮大小,getContext()),
convertDpToPixel(按钮大小,getContext())
);
iv_scale_params.gravity=gravity.BOTTOM | gravity.RIGHT;
LayoutParams iv_delete_参数=
新布局参数(
convertDpToPixel(按钮大小,getContext()),
convertDpToPixel(按钮大小,getContext())
);
iv_delete_params.gravity=gravity.TOP | gravity.RIGHT;
布局参数iv_flip_参数=
新布局参数(
convertDpToPixel(按钮大小,getContext()),
convertDpToPixel(按钮大小,getContext())
);
iv_flip_params.gravity=gravity.TOP | gravity.LEFT;
this.setLayoutParams(this_-params);
this.addView(getMainView(),iv_main_参数);
this.addView(iv_border,iv_border_params);
此.addView(iv_比例,iv_比例参数);
this.addView(iv_delete,iv_delete_参数);
this.addView(iv_flip,iv_flip_参数);
this.setOnTouchListener(mTouchListener);
这个.iv_刻度.setOnTouchListener(mTouchListener);
this.iv_delete.setOnClickListener(新的OnClickListener(){
@凌驾
公共void onClick(视图){
if(stickview.this.getParent()!=null){
ViewGroup myCanvas=((ViewGroup)StickView.this.getParent());
myCanvas.removeView(stickview.this);
}
}
});
this.iv_flip.setOnClickListener(新的OnClickListener(){
@凌驾
公共void onClick(视图){
Log.v(标记“翻转视图”);
/*View mainView=getMainView();
mainView.setRotationY(mainView.getRotationY()==-180f?0f:-180f);
mainView.invalidate();
requestLayout()*/
iv_边框设置可见性(视图不可见);
iv_比例设置可见性(视图不可见);
iv_删除.设置可见性(视图.不可见);
iv_翻转设置可见性(视图不可见);
}
});
}
公共布尔值isFlip(){
返回getMainView().getRotationY()==-180f;
}
受保护的抽象视图getMainView();
私有OnTouchListener mTouchListener=新OnTouchListener(){
@凌驾
公共布尔onTouch(视图、运动事件){
if(view.getTag().equals(“DragableViewGroup”)){
开关(event.getAction()){
case MotionEvent.ACTION\u DOWN:
Log.v(标签“标签视图动作向下”);
move_orgX=event.getRawX();
move_orgY=event.getRawY();
打破
case MotionEvent.ACTION\u移动:
Log.v(标签,“标签视图”活动