自定义TextView实现单指拖动,双指缩放旋转

由于在网上找到的教程中双指旋转需要通过获取手指落点相对于父控件的坐标点来计算,所以采用重写RelativeLayout的方法,如果有其他的方法不需要重写RelativeLayout,希望可以和我联系

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事件发生时,手指相对于view左上角x轴的距离
    private float starty;// down事件发生时,手指相对于view左上角y轴的距离
    private float endx; // move事件发生时,手指相对于view左上角x轴的距离
    private float endy; // move事件发生时,手指相对于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的坐标
                        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的坐标
                        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  {

                            //处理旋转模块
                            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) {
                            //监听事件,在MainActivity中实现,否则不能调用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);
    }

    /**
     * 计算刚开始触摸的两个点构成的直线和滑动过程中两个点构成直线的角度
     *
     * @param fX  初始点一号x坐标
     * @param fY  初始点一号y坐标
     * @param sX  初始点二号x坐标
     * @param sY  初始点二号y坐标
     * @param nfX 终点一号x坐标
     * @param nfY 终点一号y坐标
     * @param nsX 终点二号x坐标
     * @param nsY 终点二号y坐标
     * @return 构成的角度值
     */
    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();
    }
}

如果想要监听其中TextView的点击事件,可以设置接口

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

    public interface textClick {
        void onTextClick();
    }

在MainActivity.java中实现如下

    @Override
    public void onTextClick() {
        mPoemLayout.setVisibility(View.INVISIBLE);
        textCustom();
        textCustomLayout.setVisibility(View.VISIBLE);
        Toast.makeText(this, "hahaha", Toast.LENGTH_LONG).show();
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容