5大方法完美解决View的移动:layout(),offsetLeftAndRight(),MarginLayoutParams,动画,scrollTo
借鉴自Android进阶之光,刘望舒的好书!
(
此外再介绍各个阶段应该看的书:
入门 第一行代码
中阶 Android群英传(偏UI) Android进阶之光(偏业务)
高阶 Android开发艺术探索 (还有一本源代码解析好像挺不错的,不过我没看过)
)
(这里采用自定义控件的方式,接下来我会写更具体的应用场景)
自定义控件继承自View,里面就一个简单的方法,用来监听手势的,然后在布局文件中引用这个自定义控件就可以(后面我会给出完整代码)
public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = x; lastY = y; break; case MotionEvent.ACTION_MOVE: int offsetX = x - lastX; int offsetY = y - lastY; //1.layout //getTop()就是顶部距离父容器顶部, //getTop()就是底部距离父容器顶部 // layout(getLeft() + offsetX, getTop() + offsetY, // getRight() + offsetX, getBottom() + offsetY); //2.offsetLeftAndRight() //类似方法1 // offsetLeftAndRight(offsetX); // offsetTopAndBottom(offsetY); //3.改变布局参数(1)LayoutParams(根据不同父布局选择),这里是ConstraintLayout //(2)ViewGroup的MarginLayoutParams //测试发现用不了 // ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) // getLayoutParams(); // ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) // getLayoutParams(); // layoutParams.leftMargin = getLeft() + offsetX; // layoutParams.topMargin = getTop() + offsetY; // setLayoutParams(layoutParams); //4.属性动画(相比普通动画,是真是移动了位置,而不是表象) //不用在这里定义 //5.scrollTo,scrollBy // ((View)getParent()).scrollBy(-offsetX, -offsetY); break; } return true; }其中1235方法这里用就可以了,4动画是这样用的。
1.res下新建anim文件夹,新建translate.xml,以下是内容
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <!--fillAfter让动画执行好后不回去--> <!--duration 时间;fromXDelta 起始X位置;toXDelta 终点X位置--> <translate android:duration="1000" android:fromXDelta="0" android:toXDelta="300" /> </set>2.普通动画是需要这样的xml文件的
@BindView(R.id.slidingView) SlidingView mSlidingView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_view_translate); ButterKnife.bind(this); //4(1).普通动画 // mSlidingView.setAnimation(AnimationUtils.loadAnimation(this, R.anim.translate)); //4(2).属性动画 // ObjectAnimator.ofFloat(mSlidingView, "translationX", 0, 300).setDuration(1000).start();3.而属性动画不用这样,一句话就可以了。
还有一个问题:为什么
//5.scrollTo,scrollBy // ((View)getParent()).scrollBy(-offsetX, -offsetY);scroller的参数要反着来,可以把所有的内容看成是放在画布上的,可能这个画布很大,有些内容你手机看不到
这个时候你移动的,是画布,而不是那个控件,所以自然要反着来。
以下是自定义控件所有代码
public class SlidingView extends View { public SlidingView(Context context) { super(context); } public SlidingView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public SlidingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } private int lastX; private int lastY; public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = x; lastY = y; break; case MotionEvent.ACTION_MOVE: int offsetX = x - lastX; int offsetY = y - lastY; //1.layout //getTop()就是顶部距离父容器顶部, //getTop()就是底部距离父容器顶部 // layout(getLeft() + offsetX, getTop() + offsetY, // getRight() + offsetX, getBottom() + offsetY); //2.offsetLeftAndRight() //类似方法1 // offsetLeftAndRight(offsetX); // offsetTopAndBottom(offsetY); //3.改变布局参数(1)LayoutParams(根据不同父布局选择),这里是ConstraintLayout //(2)ViewGroup的MarginLayoutParams //测试发现用不了 // ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) // getLayoutParams(); // ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) // getLayoutParams(); // layoutParams.leftMargin = getLeft() + offsetX; // layoutParams.topMargin = getTop() + offsetY; // setLayoutParams(layoutParams); //4.属性动画(相比普通动画,是真是移动了位置,而不是表象) //不用在这里定义 //5.scrollTo,scrollBy // ((View)getParent()).scrollBy(-offsetX, -offsetY); //6.Scroller break; } return true; } }自定义控件的引用
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.test.ViewTranslateActivity"> <com.example.test.widget.SlidingView android:id="@+id/slidingView" android:layout_width="50dp" android:layout_height="50dp" android:background="@color/colorPrimaryDark"/> </android.support.constraint.ConstraintLayout>