Android控件架构与自定义控件详解(三)——自定义ViewGroup
来源:互联网 发布:php 获取请求url 编辑:程序博客网 时间:2024/05/20 12:48
ViewGroup存在的目的就是为了对其子View进行管理,为其子View添加显示、响应的规则。因此,自定义ViewGroup通常需要重写onMeasure()方法来对子View进行测量,重写onLayout()方法来确定子View的位置,重写onTouchEvent()方法增加响应事件。
本例将实现一个类似Android原生控件ScrollView的自定义ViewGroup,且在滑动的过程中,增加一个粘性的效果,效果图如下:
代码如下:
package com.example.huangfei.myapplication;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.widget.Scroller;/** * Created by huangfeihong on 2016/5/15. * 具有粘性效果的ScrollView * 先让自定义ViewGroup实现类似ScrollView的功能,再添加粘性效果 */public class MyScrollView extends ViewGroup { private int mScreenHeight; private Scroller mScroller; private int mLastY; private int mStart; private int mEnd; 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) { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); mScreenHeight = metrics.heightPixels; //让每个子View都显示完整的一屏 mScroller = new Scroller(context); } /** * 先对其子View进行测量 * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int count = getChildCount(); for (int i = 0; i < count; i++) { View childView = getChildAt(i); measureChild(childView, widthMeasureSpec, heightMeasureSpec); } } /** * 对其子View进行放置位置的设定 * @param changed * @param l * @param t * @param r * @param b */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); // 设置ViewGroup的高度 MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams(); mlp.height = childCount * mScreenHeight; setLayoutParams(mlp); //让每个子View依次下排 for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); if(childView.getVisibility() != View.GONE){ childView.layout(l, i * mScreenHeight, r, (i + 1) * mScreenHeight); } } } /** * 在ViewGroup中添加滑动事件,可以使用scrollBy()方法来辅助滑动 * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { int y = (int) event.getY(); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: mLastY = y; //记录触摸起点 mStart = getScrollY(); break; case MotionEvent.ACTION_MOVE: if(!mScroller.isFinished()){ mScroller.abortAnimation(); } int dy = mLastY - y; if(getScrollY() < 0 && dy < 0) dy = 0; if(getScrollY() > getHeight() - mScreenHeight && dy > 0) dy = 0; scrollBy(0, dy); mLastY = y; break; case MotionEvent.ACTION_UP: //记录触摸终点 //mEnd = getScrollY(); //int dScrollY = mEnd - mStart; int dScrollY = checkAlignment(); //实现粘性效果,滑动距离大于子View的1/3,则使用Scroller类来平滑到下一个子View,否则就会回滚 //到原来的位置 if(dScrollY > 0){//向上滑动 if(dScrollY < mScreenHeight / 3){ mScroller.startScroll(0, getScrollY(), 0, -dScrollY); }else{ mScroller.startScroll(0, getScrollY(), 0, mScreenHeight - dScrollY); } }else{//向下滑动 if(-dScrollY < mScreenHeight / 3){ mScroller.startScroll(0, getScrollY(), 0, -dScrollY); }else{ mScroller.startScroll(0, getScrollY(), 0, - mScreenHeight - dScrollY); } } break; } postInvalidate(); return true; } /** * 获取手指滑动的距离 * @return */ private int checkAlignment() { int mEnd = getScrollY(); boolean isUp = ((mEnd - mStart) > 0) ? true : false; int lastPrev = mEnd % mScreenHeight; int lastNext = mScreenHeight - lastPrev; if (isUp) { //向上的 return lastPrev; } else { return -lastNext; } } @Override public void computeScroll() { super.computeScroll(); if(mScroller.computeScrollOffset()){ scrollTo(0, mScroller.getCurrY()); postInvalidate(); } }}
代码地址
0 0
- Android控件架构与自定义控件详解(三)——自定义ViewGroup
- Android控件架构与自定义控件详解(三)自定义ViewGroup
- 3.4.Android控件架构与自定义控件详解之ViewGroup的测量与绘制
- Android 控件架构与自定义控件(三)
- Android控件架构与自定义控件详解(二)——自定义View
- Android控件架构与自定义控件详解
- Android控件架构与自定义控件详解
- Android控件架构与自定义控件详解
- Android 控件架构与自定义控件详解
- Android控件架构与自定义控件详解(一)——Android控件架构与View的绘制原理
- android控件架构、自定义View、ViewGroup
- Android控件架构与自定义控件详解(四)——事件拦截机制分析
- 3.5Android控件架构与自定义控件详解之自定义View(三)
- Android 自定义ViewGroup控件
- Android自定义控件 -- 自定义ViewGroup
- Android控件构架与自定义控件详解(一)Android控件架构与自定义控件绘制原理
- Android群英传知识点回顾——第三章:Android控件架构与自定义控件详解
- 《Android群英传》阅读笔记——第三章:Android控件架构与自定义控件详解
- 计算机视觉-相机内参数和外参数
- java矩阵运算包ujmp中的一些小示例和注意事项
- C#遍历DataSet中数据的方法总结
- THREE.JS中常用的3种材质
- 天了噜,玩家竟能写出这样的文章来!
- Android控件架构与自定义控件详解(三)——自定义ViewGroup
- 用C语言实现控制台模拟显示时
- vector类c++ && BFS
- 双色球模拟实验
- unix文件和i/o流
- vxlan-SDK-nsx_integration-vxlan_xorp
- Block究竟在哪
- vxlan概述
- AspectJ切入点语法详解