Muốn kéo view di chuyển tự do toàn màn hình, ta có thể dùng
service để làm. Tuy nhiên có những app ta không muốn dùng service, ta sẽ làm ngay
trong activity.
Muốn di chuyển view nào đó dọc theo một layout cố định, ta làm như
sau.
Tạo một file xml tên keoview trong
layout như sau.
<?xml version="1.0"
encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:orientation="vertical"
>
<TextView
android:layout_width="130dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:text="Đây là view
kéo được"
android:textColor="#FF0000"
/>
<RelativeLayout
android:id="@+id/root"
android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_gravity="center" >
<TextView
android:id="@+id/te"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_centerVertical="true"
android:background="#2292CB"
android:text="Chạm để
kéo" />
</RelativeLayout>
</LinearLayout>
Đây là class để kéo view
public class keo extends Activity implements View.OnTouchListener {
private int _yDelta;
LayoutParams params;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.keoview);
findViewById(R.id.te).setOnTouchListener(this);
params
= new
WindowManager.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT, LayoutParams.TYPE_PHONE,
LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);
}
@Override
public boolean onTouch(View view, MotionEvent event) {
final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
_yDelta = Y - lParams.bottomMargin;
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
layoutParams.bottomMargin = (Y - _yDelta);
layoutParams.topMargin = -layoutParams.bottomMargin;
view.setLayoutParams(layoutParams);
view.animate().translationY(Y - _yDelta).setDuration(0);
break;
}
findViewById(R.id.root).invalidate();
return true;
}
}
Để kéo view ngang màn hình, ta sửa file keoview.xml để cho
chiều ngang của Linearlayout và RelativeLayout thành
android:layout_width="match_parent"
Trong class, thêm vào một biến.
private int _xDelta;
Lệnh onTouch bây giờ như sau.
@Override
public boolean onTouch(View view, MotionEvent event) {
final int X = (int) event.getRawX();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
_xDelta = X - lParams.leftMargin;
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
layoutParams.leftMargin = (X - _xDelta);
layoutParams.rightMargin = -layoutParams.leftMargin;
view.setLayoutParams(layoutParams);
view.animate().translationX(X - _xDelta).setDuration(0);
break;
}
findViewById(R.id.root).invalidate();
return true;
}
Muốn kéo view tự do trên màn hình, ta kết hợp cả 2 vào.
@Override
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:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.bottomMargin;
break;
case MotionEvent.ACTION_UP:
dem=dem+1;
if(dem==2){
Toast.makeText(getApplicationContext(),
"Có chạm
view", Toast.LENGTH_LONG).show();
dem=0;
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
layoutParams.bottomMargin = (Y - _yDelta);
layoutParams.topMargin = -layoutParams.bottomMargin;
layoutParams.leftMargin = (X - _xDelta);
layoutParams.rightMargin = -layoutParams.leftMargin;
view.setLayoutParams(layoutParams);
view.animate().translationX(X - _xDelta).setDuration(0);
view.animate().translationY(Y - _yDelta).setDuration(0);
break;
}
findViewById(R.id.root).invalidate();
return true;
}
Lệnh trong case MotionEvent.ACTION_UP: là để khi
chạm 2 lần vào view thì thực hiện tác vụ nào đó, ở đây là show ra thông báo có
chạm. Chú ý phải khai báo thêm biến dem. Lệnh này có hạn chế là cứ
kéo view 2 lần là nó show toast ra. Nên bạn có thể tham khảo cách phát hiện có
chạm view ở bài kéo view nổi trên màn hình dùng service để làm cách khác ưng ý
hơn.
Tại bài này cũng có hướng dẫn dùng SharedPreferences để lưu vị trí view đã di chuyển
tới, lần sau mở ra thì view vẫn ở vị trí đã kéo tới chứ không phải lại về vị
trí ban đầu.
Cách này có ưu điểm là khi chạy rất nhẹ, không gây crash app.
No comments:
Post a Comment