zoukankan      html  css  js  c++  java
  • 安卓进阶之自定义View的基础二

    View滑动的基本思想:当点击事件传到View时,系统记下触摸点的坐标,手指移动时系统记下触摸后的坐标并计算出偏移量,然后根据偏移量修正View坐标.

    实现View滑动共有6种方法:layout()方法,offsetTopAndBottom(),LayoutParams,动画,scrollTo与scrollBy,以及Scroller.

    一.layout()

    import ...;
    
    public class CustomView extends View {
        private int lastX;
        private int lastY;
    
        public CustomView(Context context) {
            super(context);
        }
    
        public CustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        public CustomView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        @Override
        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;
            //修改View的left,top,right,bottom属性重新放置View layout(getLeft()
    + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY); break; } return true; } }

    然后在布局文件中引用就好了:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 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=".MainActivity"
        android:orientation="vertical"
        >
    
        <com.example.scroll_test.CustomView
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:background="@color/colorAccent"
            />
    
    </LinearLayout>

    二.offsetLeftandRight

    这种方法与Layout()方法相似,只需将ACTION_MOVE修改成以下代码:

                case MotionEvent.ACTION_MOVE:
                    int offsetX = x - lastX;
                    int offsetY = y - lastY;
                    offsetLeftAndRight(offsetX);
                    offsetTopAndBottom(offsetY);
                    break;
            }

    三.LayoutParams(改变布局参数)

    通过LayoutParams改变View的布局参数,从而达到修改View位置的效果.

     将ACTION_MOVE修改成以下代码:

                case MotionEvent.ACTION_MOVE:
                    int offsetX = x - lastX;
                    int offsetY = y - lastY;
               LinearLayout.LayoutParams layoutParams
    = (LinearLayout.LayoutParams) getLayoutParams(); layoutParams.leftMargin=getLeft() + offsetX; layoutParams.topMargin=getTop() + offsetY; setLayoutParams(layoutParams); break; }

    由于父控件是LinearLayout,所以用到了LineatLayout.LayoutParams.如果是RelativeLayout,则要使用RelativeLayot.LayoutParams.还可以用ViewGroup.MarginLayoutParams来实现:

    ViewGroup.MarginLayoutParams layoutParams= (LinearLayout.LayoutParams) getLayoutParams();
                    layoutParams.leftMargin=getLeft() + offsetX;
                    layoutParams.topMargin=getTop() + offsetY;
                    setLayoutParams(layoutParams);
                    

    四.属性动画

    ObjectAnimator.ofFloat(mCustomView,"translationX",0,300).setDuration().start();

    五.scrollTo与scrollBy

    scrollTo(x,y)表示移动到一个具体的点,scrollBy(dx,dy)表示移动的增量为dx,dy.

    scrollTo,scrollBy移动的是View的内容,如果在ViewGround中使用,则是移动其所有的子View..我们将ACTION_MOVE替换成如下代码:

    ((View)getParent()).scrollBy(-offsetX,-offsetY);

    设置为负值,则CustomView会跟随手滑动.原因是因为此时移动的是手机屏幕,布局是不移动的.布局中的控件也是不懂的,手指向右滑动后,想要View也向右滑动,则要把手机屏幕向着左边滑动,则布局相对向右滑动,实现跟手的效果.

    六.Scroller

    这个方法的实现效果比较类似动画,不过与动画相比其只可以用来实现滑动效果.

    首先要初始化这个scroller:

    public CustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
            scroller=new Scroller(context);
        }

    接下来重写computeScroll()方法,该方法会在View绘制时的draw()中调用

    @Override
        public void computeScroll() {
            super.computeScroll();
            if(scroller.computeScrollOffset()){
              ((View)getParent()).scrollTo(scroller.getCurrX(),scroller.getCurrY());
              //通过不断调用invalidate(),不断返回调用computeScroll,更新View位置
          // 直到scroller.computeScrolloffset返回fasle(即dutation结束)
          invalidate(); } }

    同时在CustomView中写一个方法:

     public void smoothScrollTo(int destX,int dextY){
            int scrollX=getScrollX();
            int deltaX=destX-scrollX;

         //
    startScroll (int startX, int startY, int dx, int dy, int duration)
            scroller.startScroll(scrollX,0,deltaX,0,2000);
            invalidate();
        }

    通过在代码中调用自定义控件的smoothScrollTo方法,可以实现View的滑动效果.

    
    
  • 相关阅读:
    正则表达式验证日期(多种日期格式)——转载
    NPOI导出Excel——精简版
    Ubuntu下安装部署.NET Core多版本环境
    搭建 nuget 私用库 BaGet
    ubuntu 监听端口
    搭建npm 私用库 verdaccio
    pgsql 性能测试 pgbench
    docker-compose 创建网络
    安装 docker-compose 启动
    dotnet sdk安装以及环境变量设置 Ubuntu 18.04 LTS
  • 原文地址:https://www.cnblogs.com/adressian/p/10771040.html
Copyright © 2011-2022 走看看