第一类原理:layout方式
1、直接调用viewgroup的layout()方法来layout子view。麻烦的是你要计算出left、top、right、bottom这四个参数的值
2、使用MarginLayoutParam,使view的外层ViewGroup来layout该view。一般都这么写:
ViewGroup.MarginLayoutParams layoutParams = view.getLayoutParams(); // layoutParams.bottomMargin = // layoutParams.leftMargin = view.requestLayout();
第二类:scrollTo
适用于容器的内容的长度大于该view的可见区,例如scrollview。
第三类:view的setTranslationY和setTranslationX
第四类:view.offsetLeftAndRight(offset)和offsetTopAndBottom(offset)
手势相关: GestureDetector:无限制ViewDragHelper:用在自定义viewgroup中。
GestureDetector用法:
view.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event);
return false;
}
});
或者在自定义view的onTouchEvent()中gestureDetector.onTouchEvent(event);Listener一般用GestureDetector.SimpleOnGestureListener
ViewDragHelper用法:
package com.example.vdh;
import android.content.Context;
import android.graphics.Point;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
/**
* ViewDragHelper 的使用
*
*/
public class VDHLayout extends LinearLayout {
private ViewDragHelper mDragger;
private View mFirstView,mSecondView,mThirdView;
private Point secondPosition = new Point(); //记录第二个view的左和顶部的位置
public VDHLayout(Context context) {
super(context);
}
public VDHLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mDragger = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback()
{
@Override
public boolean tryCaptureView(View child, int pointerId)
{
//mFirstView禁止直接移动
return child == mSecondView || child == mThirdView;
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx)
{
return left;
}
@Override
public int clampViewPositionVertical(View child, int top, int dy)
{
return top;
}
//手指释放的时候回调
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel)
{
//mAutoBackView手指释放时可以自动回去
if (releasedChild == mSecondView)
{
mDragger.settleCapturedViewAt(secondPosition.x, secondPosition.y);
invalidate();
}
}
//在边界拖动时回调
@Override
public void onEdgeDragStarted(int edgeFlags, int pointerId)
{
mDragger.captureChildView(mFirstView, pointerId);
}
});
mDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
}
public VDHLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptHoverEvent(MotionEvent event) {
return mDragger.shouldInterceptTouchEvent(event); //由mDragger来处理intercept
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mDragger.processTouchEvent(event);
return true; //mDragger已处理,直接返回true
}
@Override
public void computeScroll() {
if(mDragger.continueSettling(true)){
invalidate();
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed,l,t,r,b);
//记住mSecondView的位置
secondPosition.x = mSecondView.getLeft();
secondPosition.y = mSecondView.getTop();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mFirstView = getChildAt(0);
mSecondView = getChildAt(1);
mThirdView = getChildAt(2);
}
}
Activity中xml布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, MyActivity"
/>
<com.example.vdh.VDHLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<View android:layout_width="80dp" android:layout_height="80dp"
android:background="#666666"/>
<View android:layout_width="80dp" android:layout_height="80dp"
android:background="#ee6666"/>
<View android:layout_width="80dp" android:layout_height="80dp"
android:background="#55ff66"/>
</com.example.vdh.VDHLayout>
</LinearLayout>
效果:
参考:http://blog.csdn.net/lmj623565791/article/details/46858663
http://blog.csdn.net/pi9nc/article/details/39583377
ViewDragHelper:用在自定义viewgroup中。
GestureDetector用法:
或者在自定义view的onTouchEvent()中gestureDetector.onTouchEvent(event);Listener一般用GestureDetector.SimpleOnGestureListenerview.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { gestureDetector.onTouchEvent(event); return false; } });
ViewDragHelper用法:
package com.example.vdh; import android.content.Context; import android.graphics.Point; import android.support.v4.widget.ViewDragHelper; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; /** * ViewDragHelper 的使用 * */ public class VDHLayout extends LinearLayout { private ViewDragHelper mDragger; private View mFirstView,mSecondView,mThirdView; private Point secondPosition = new Point(); //记录第二个view的左和顶部的位置 public VDHLayout(Context context) { super(context); } public VDHLayout(Context context, AttributeSet attrs) { super(context, attrs); mDragger = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() { @Override public boolean tryCaptureView(View child, int pointerId) { //mFirstView禁止直接移动 return child == mSecondView || child == mThirdView; } @Override public int clampViewPositionHorizontal(View child, int left, int dx) { return left; } @Override public int clampViewPositionVertical(View child, int top, int dy) { return top; } //手指释放的时候回调 @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { //mAutoBackView手指释放时可以自动回去 if (releasedChild == mSecondView) { mDragger.settleCapturedViewAt(secondPosition.x, secondPosition.y); invalidate(); } } //在边界拖动时回调 @Override public void onEdgeDragStarted(int edgeFlags, int pointerId) { mDragger.captureChildView(mFirstView, pointerId); } }); mDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT); } public VDHLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean onInterceptHoverEvent(MotionEvent event) { return mDragger.shouldInterceptTouchEvent(event); //由mDragger来处理intercept } @Override public boolean onTouchEvent(MotionEvent event) { mDragger.processTouchEvent(event); return true; //mDragger已处理,直接返回true } @Override public void computeScroll() { if(mDragger.continueSettling(true)){ invalidate(); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed,l,t,r,b); //记住mSecondView的位置 secondPosition.x = mSecondView.getLeft(); secondPosition.y = mSecondView.getTop(); } @Override protected void onFinishInflate() { super.onFinishInflate(); mFirstView = getChildAt(0); mSecondView = getChildAt(1); mThirdView = getChildAt(2); } }
Activity中xml布局:<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello World, MyActivity" /> <com.example.vdh.VDHLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <View android:layout_width="80dp" android:layout_height="80dp" android:background="#666666"/> <View android:layout_width="80dp" android:layout_height="80dp" android:background="#ee6666"/> <View android:layout_width="80dp" android:layout_height="80dp" android:background="#55ff66"/> </com.example.vdh.VDHLayout> </LinearLayout>
效果:参考:http://blog.csdn.net/lmj623565791/article/details/46858663
http://blog.csdn.net/pi9nc/article/details/39583377