android上下滑动选择控件,Android自定义控件ScrollView实现上下滑动功能

本文实例为大家分享了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个值和屏幕方向无关。

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值