5大方法完美解决View的移动:layout(),offsetLeftAndRight(),MarginLayoutParams,动画,scrollTo

来源:互联网 发布:数控线切割编程软件 编辑:程序博客网 时间:2024/06/07 15:53

借鉴自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>

阅读全文
0 0
原创粉丝点击