首页 > 系统 > Android > 正文

Android自定义控件ScrollView实现上下滑动功能

2019-10-21 21:45:46
字体:
来源:转载
供稿:网友

本文实例为大家分享了Android ScrollView实现上下滑动功能的具体代码,供大家参考,具体内容如下

package com.example.zhuang;import android.content.Context;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.Scroller;public class MyScrollView extends ViewGroup {  private int mScreeHeight;//屏幕高度  private Scroller mScroller;  private int mLastY;  private int mStart;  private int mEnd;  private Context context;  public MyScrollView(Context context) {    super(context);    initView(context);  }  public MyScrollView(Context context, AttributeSet attrs) {    super(context, attrs);    initView(context);  }  public MyScrollView(Context context, AttributeSet attrs,            int defStyleAttr) {    super(context, attrs, defStyleAttr);    initView(context);  }  private void initView(Context context) {    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);    //DisplayMetrics 类提供了一种关于显示的通用信息,如显示大小,分辨率和字体。    DisplayMetrics dm = new DisplayMetrics();    wm.getDefaultDisplay().getMetrics(dm);    mScreeHeight = dm.heightPixels;//高度(像素)    mScroller = new Scroller(context);  }  //继承ViewGroup必须要实现的方法  @Override  protected void onLayout(boolean changed, int l, int t, int r, int b) {    int childCount = getChildCount();//获取子view的个数    //设置ViewGroup的高度    MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();    mlp.height = mScreeHeight * childCount;    setLayoutParams(mlp);    for (int i = 0; i < childCount; i++) {      View child = getChildAt(i);      if (child.getVisibility() != View.GONE) {        //参数为相对父容器的左上右下位置,第三个参数必须为r        child.layout(0, i * mScreeHeight, r, (i + 1) * mScreeHeight);      }    }  }  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    int count = getChildCount();    for (int i = 0; i < count; i++) {      View child = getChildAt(i);      measureChild(child, widthMeasureSpec, heightMeasureSpec);    }  }  @Override  public boolean onTouchEvent(MotionEvent event) {    int y = (int) event.getY();//相对于view的y值,getRawY()是相对屏幕    switch (event.getAction()) {      case MotionEvent.ACTION_DOWN:        mLastY = y;//上一次的y值        mStart = getScrollY();//记录触摸起点        break;      case MotionEvent.ACTION_MOVE:        if(!mScroller.isFinished()) {          mScroller.abortAnimation();//放弃移到最终位置        }        int dy = mLastY - y;//偏移距离        //如果滑动距离小于0或大于屏幕高度,不偏移        if(getScrollY()<0){          dy = 0;        }        if(getScrollY() > getHeight()-mScreeHeight){          dy = 0;        }        scrollBy(0,dy);//移动        mLastY = y;        break;      case MotionEvent.ACTION_UP:        int dScrollY = checkAlignment();//整体移动的距离        if(dScrollY > 0){          if(dScrollY < mScreeHeight / 3){            mScroller.startScroll(0,getScrollY(),0,-dScrollY);          }else{            mScroller.startScroll(0,getScrollY(),0,mScreeHeight-dScrollY);          }        }else{          if(-dScrollY < mScreeHeight / 3){            mScroller.startScroll(0,getScrollY(),0,-dScrollY);          }else{            mScroller.startScroll(0,getScrollY(),0,-mScreeHeight-dScrollY);          }        }        break;    }    postInvalidate();    return true;  }  private int checkAlignment(){     mEnd = getScrollY();//记录触摸终点    boolean isUp = ((mEnd - mStart)>0) ? true : false;    int lastPrev = mEnd % mScreeHeight;    int lastNext = mScreeHeight - lastPrev;    if(isUp){      return lastPrev;//向上    }else      return -lastNext;  }  @Override  public void computeScroll() {    super.computeScroll();    if(mScroller.computeScrollOffset()){//返回true,表示还未移动完      scrollTo(0,mScroller.getCurrY());//移到当前位置      postInvalidate();      //invalidate()是用来刷新View的,必须是在UI线程中进行工作。      //postInvalidate()可以在非UI线程调用    }  }}

知识点:

1、获取屏幕参数代码:

DisplayMetrics metric = new DisplayMetrics(); //API 17之后使用,获取的像素宽高包含虚拟键所占空间,在API 17之前通过反射获取 context.getWindowManager().getDefaultDisplay().getRealMetrics(metric); //获取的像素宽高不包含虚拟键所占空间 //context.getWindowManager().getDefaultDisplay().getMetrics(metric); int width = metric.widthPixels; // 宽度(像素) int height = metric.heightPixels; // 高度(像素) float density = metric.density; // dp缩放因子 int densityDpi = metric.densityDpi; // 广义密度 float xdpi = metric.xdpi;//x轴方向的真实密度 float ydpi = metric.ydpi;//y轴方向的真实密度 

屏幕高度值包含了状态栏的像素,非沉浸模式下真实的Activity高度需要减去状态栏的高度。获取状态栏高度代码:

private int getStatusBarHeight() {   Rect rect = new Rect();   getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);   return rect.top; } 

屏幕参数Width和Height的值和屏幕方向有关,另外4个值和屏幕方向无关。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表