自定義TextView實現(xiàn)單指拖動,雙指縮放旋轉(zhuǎn)

由于在網(wǎng)上找到的教程中雙指旋轉(zhuǎn)需要通過獲取手指落點相對于父控件的坐標(biāo)點來計算,所以采用重寫RelativeLayout的方法,如果有其他的方法不需要重寫RelativeLayout,希望可以和我聯(lián)系

MyRelativeLayout.java
/**
 * Created by nan on 2017/5/27.
 */

public class MyRelativeLayout extends RelativeLayout {

    private TextView mytextview;
    private static LinearLayout textCustomLayout;

    private float startx;// down事件發(fā)生時,手指相對于view左上角x軸的距離
    private float starty;// down事件發(fā)生時,手指相對于view左上角y軸的距離
    private float endx; // move事件發(fā)生時,手指相對于view左上角x軸的距離
    private float endy; // move事件發(fā)生時,手指相對于view左上角y軸的距離
    private float left; // DragTV左邊緣相對于父控件的距離
    private float top; // DragTV上邊緣相對于父控件的距離
    private int right; // DragTV右邊緣相對于父控件的距離
    private int bottom; // DragTV底邊緣相對于父控件的距離
    private float hor; // 觸摸情況下,手指在x軸方向移動的距離
    private float ver; // 觸摸情況下,手指在y軸方向移動的距離
    private float mfX, mfY, msX, msY;
    private boolean isMove = true;
    private float mAngle;
    private int ptrID1 = INVALID_POINTER_ID, ptrID2 = INVALID_POINTER_ID;
    private float oldDist = 0;
    private float textSize = 0;
    private float scale;
    private static final int INVALID_POINTER_ID = -1;
    private MotionEvent mEvent;
    private boolean onefingure;

    public MyRelativeLayout(Context context) {
        super(context);

    }

    public MyRelativeLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyRelativeLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public textClick getTextClick() {
        return mytextClick;
    }
    public void setTextClick(textClick mytextClick) {
        this.mytextClick = mytextClick;
    }
    private textClick mytextClick;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mEvent = event;
        mytextview = (TextView) findViewById(R.id.poemtext);

        mytextview.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                mytextview = (TextView) v;
                if (textSize == 0) {
                    textSize = mytextview.getTextSize();
                }
                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:
                        onefingure = true;
                        //手指落點相對于TextView的坐標(biāo)
                        startx = event.getX();
                        starty = event.getY();
                        Log.d("HHHH", "onTouch: ACTION_DOWM " + startx);
                        ptrID1 = event.getPointerId(event.getActionIndex());
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        isMove = false;
                        onefingure = false;

                        ptrID2 = event.getPointerId(event.getActionIndex());
                        //手指落點相對于RelativeLayout的坐標(biāo)
                        msX = mEvent.getX(event.findPointerIndex(ptrID2));
                        msY = mEvent.getY(event.findPointerIndex(ptrID2));
                        mfX = mEvent.getX(event.findPointerIndex(ptrID1));
                        mfY = mEvent.getY(event.findPointerIndex(ptrID1));
                        oldDist = spacing(event);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        Log.d("HHHH", "onTouch: ACTION_MOVE ");
                        left = mytextview.getX();
                        top = mytextview.getY();
                        if (isMove) {
                            endx = event.getX();
                            endy = event.getY();
                            hor = (endx - startx);
                            ver = (endy - starty);
                            mytextview.setX(left + hor);
                            mytextview.setY(top + ver);

                        }
                        else  {

                            //處理旋轉(zhuǎn)模塊
                            float nfX, nfY, nsX, nsY, test;
                            test = event.getX(event.findPointerIndex(ptrID1));

                            nsX = mEvent.getX(event.findPointerIndex(ptrID2));
                            nsY = mEvent.getY(event.findPointerIndex(ptrID2));
                            nfX = mEvent.getX(event.findPointerIndex(ptrID1));
                            nfY = mEvent.getY(event.findPointerIndex(ptrID1));
                            mAngle = angleBetweenLines(mfX, mfY, msX, msY, nfX, nfY, nsX, nsY);
                            mytextview.setRotation(mAngle);
                            //縮放
                            float newDist = spacing(event);
                            if (newDist > oldDist + 1) {
                                zoom(newDist / oldDist);
                                oldDist = newDist;
                            }
                            if (newDist < oldDist - 1) {
                                zoom(newDist / oldDist);
                                oldDist = newDist;
                            }

                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        Log.d("HHHH", "onTouch: ACTION_UP");
                        if (onefingure) {
                            //監(jiān)聽事件,在MainActivity中實現(xiàn),否則不能調(diào)用MainActivity中的對象
                            mytextClick.onTextClick();
                        }
                        break;
                    case MotionEvent.ACTION_POINTER_UP:
                        Log.d("HHHH", "onTouch: ACTION_POINTER_UP");
                        isMove = true;
                        break;
                }
                return true;
            }
        });
        return true;
    }
    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);
    }
    private void zoom(float f) {
        mytextview.setTextSize(textSize *= f);
    }

    /**
     * 計算剛開始觸摸的兩個點構(gòu)成的直線和滑動過程中兩個點構(gòu)成直線的角度
     *
     * @param fX  初始點一號x坐標(biāo)
     * @param fY  初始點一號y坐標(biāo)
     * @param sX  初始點二號x坐標(biāo)
     * @param sY  初始點二號y坐標(biāo)
     * @param nfX 終點一號x坐標(biāo)
     * @param nfY 終點一號y坐標(biāo)
     * @param nsX 終點二號x坐標(biāo)
     * @param nsY 終點二號y坐標(biāo)
     * @return 構(gòu)成的角度值
     */
    private float angleBetweenLines(float fX, float fY, float sX, float sY, float nfX, float nfY, float nsX, float nsY) {
        float angle1 = (float) Math.atan2((fY - sY), (fX - sX));
        float angle2 = (float) Math.atan2((nfY - nsY), (nfX - nsX));

        float angle = ((float) Math.toDegrees(angle1 - angle2)) % 360;
        if (angle < -180.f) angle += 360.0f;
        if (angle > 180.f) angle -= 360.0f;
        return -angle;
    }
    public interface textClick {
        void onTextClick();
    }
}

如果想要監(jiān)聽其中TextView的點擊事件,可以設(shè)置接口

    public textClick getTextClick() {
        return mytextClick;
    }
    public void setTextClick(textClick mytextClick) {
        this.mytextClick = mytextClick;
    }
    private textClick mytextClick;

    public interface textClick {
        void onTextClick();
    }

在MainActivity.java中實現(xiàn)如下

    @Override
    public void onTextClick() {
        mPoemLayout.setVisibility(View.INVISIBLE);
        textCustom();
        textCustomLayout.setVisibility(View.VISIBLE);
        Toast.makeText(this, "hahaha", Toast.LENGTH_LONG).show();
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容