Android——控件跟随手指移动

Android开发中遇到过的坑——控件跟随手指移动

思路

实现任意控件跟随手指触摸移动。核心思路监听onTouch事件,在ACTION_MOVE中改变控件的坐标。思路虽然简单,但其中还有一些坑。
本文的思路借鉴了http://blog.csdn.net/actual_/article/details/8582313这位博主的代码,但他的代码有个Bug,即当拖动控件到屏幕中间位置时控件会变形,分析其代码,主要问题出现在:

case MotionEvent.ACTION_MOVE:  
            RelativeLayout.LayoutParams layoutParams =    (RelativeLayout.LayoutParams) view  
                    .getLayoutParams();  
            layoutParams.leftMargin = X - _xDelta;  
            layoutParams.topMargin = Y - _yDelta;  
            layoutParams.rightMargin = -250;  
            layoutParams.bottomMargin = -250;  
            view.setLayoutParams(layoutParams);  
            break;  

其中设置了控件上、下、左、右元素间隔的距离,从而完成在RelativeLayout布局中对于控件位置的设置,但是当左右间隔或上下间隔之和不对的时候,则会挤压控件的长宽。

这里换一个思路,其实只设置控件距上、左元素的距离即可完成RelativeLayout布局中控件位置的设置,并设置控件的长宽,保持其形状大小不变。

case MotionEvent.ACTION_MOVE:  
                int dx = (int) event.getRawX() - lastX;
                int dy = (int) event.getRawY() - lastY;
                int left = view.getLeft() + dx;
                int top = view.getTop() + dy;
                RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view 
                        .getLayoutParams();  
                layoutParams.height=IMAGE_SIZE;
                layoutParams.width = IMAGE_SIZE;
                layoutParams.leftMargin =left;  
                layoutParams.topMargin =top;  
                view.setLayoutParams(layoutParams);
                lastX = (int) event.getRawX();
                lastY = (int) event.getRawY();
                break;  

主要代码

MainActivity.java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;


public class MainActivity extends AppCompatActivity implements OnTouchListener {
    ImageView _view,_view2;  
    ViewGroup _root;  
    private int lastX, lastY;
    final static int IMAGE_SIZE = 72; 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        _root = (ViewGroup) findViewById(R.id.root);  

        _view = (ImageView) findViewById(R.id.id_text);  
        _view2 = (ImageView) findViewById(R.id.id_text2); 

        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(  
                IMAGE_SIZE, IMAGE_SIZE);  
        layoutParams.leftMargin = IMAGE_SIZE;  
        layoutParams.topMargin = IMAGE_SIZE;  

        _view.setLayoutParams(layoutParams);  
        _view.setOnTouchListener(this); 
        RelativeLayout.LayoutParams layoutParams2 = new RelativeLayout.LayoutParams(  
                IMAGE_SIZE, IMAGE_SIZE);  
        layoutParams2.leftMargin = 3*IMAGE_SIZE;  
        layoutParams2.topMargin = IMAGE_SIZE;  

        _view2.setLayoutParams(layoutParams2);  
        _view2.setOnTouchListener(this);  
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

     public boolean onTouch(View view, MotionEvent event) {  
            final int X = (int) event.getRawX();  
            final int Y = (int) event.getRawY();  
            switch (event.getAction() & MotionEvent.ACTION_MASK) {  
            case MotionEvent.ACTION_DOWN:  
                lastX = (int) event.getRawX();
                lastY = (int) event.getRawY();
                RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view  
                        .getLayoutParams();   
                break;  
            case MotionEvent.ACTION_UP:  
                break;  
            case MotionEvent.ACTION_POINTER_DOWN:  
                break;  
            case MotionEvent.ACTION_POINTER_UP:  
                break;  
            case MotionEvent.ACTION_MOVE:  
                int dx = (int) event.getRawX() - lastX;
                int dy = (int) event.getRawY() - lastY;
                int left = view.getLeft() + dx;
                int top = view.getTop() + dy;
                RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view 
                        .getLayoutParams();  
                layoutParams.height=IMAGE_SIZE;
                layoutParams.width = IMAGE_SIZE;
                layoutParams.leftMargin =left;  
                layoutParams.topMargin =top;  
                view.setLayoutParams(layoutParams);
                lastX = (int) event.getRawX();
                lastY = (int) event.getRawY();
                break;  
            }  
            _root.invalidate();  
            return true;  
        }  
}

activity_main.xml

这里写代码片<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:id="@+id/root"  
    tools:context=".MainActivity" >  

    <ImageView  
        android:id="@+id/id_text"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_centerHorizontal="true"  
        android:layout_centerVertical="true"  
        android:background="@drawable/pin2"
         />  
   <ImageView  
        android:id="@+id/id_text2"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_centerHorizontal="true"  
        android:layout_centerVertical="true"  
        android:background="@drawable/pin2"
        /> 
</RelativeLayout>  
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现手指在屏幕上移动,飞机跟随手指移动的效果,可以通过以下步骤实现: 1. 在布局文件中添加一个 ImageView 控件,用于显示飞机的图片。 2. 在 Java 代码中获取 ImageView 控件的实例,并为其设置触摸监听器。 3. 在触摸监听器中实现飞机跟随手指移动的逻辑: - 当手指按下时,记录下当前手指所在的坐标位置。 - 当手指移动时,计算出手指移动的距离,并根据距离调整飞机的位置。 - 当手指抬起时,取消触摸监听器。 下面是一个示例代码,可以参考实现: 首先,在布局文件中添加 ImageView 控件: ``` <ImageView android:id="@+id/ivPlane" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@drawable/plane" /> ``` 然后,在 Java 代码中获取 ImageView 控件的实例,并为其设置触摸监听器: ``` ImageView ivPlane = findViewById(R.id.ivPlane); ivPlane.setOnTouchListener(new View.OnTouchListener() { float startX, startY; float offsetX, offsetY; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: startX = event.getX(); startY = event.getY(); break; case MotionEvent.ACTION_MOVE: float endX = event.getX(); float endY = event.getY(); offsetX = endX - startX; offsetY = endY - startY; ivPlane.setX(ivPlane.getX() + offsetX); ivPlane.setY(ivPlane.getY() + offsetY); startX = endX; startY = endY; break; case MotionEvent.ACTION_UP: v.setOnTouchListener(null); break; } return true; } }); ``` 在触摸监听器中,我们记录下手指按下时的坐标位置(startX、startY),并在手指移动时计算出手指移动的距离(offsetX、offsetY),然后根据距离调整飞机的位置(ivPlane.setX()、ivPlane.setY())。最后,在手指抬起时取消触摸监听器,避免继续响应触摸事件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值