【Android】Android自定义ViewGroup
来源:互联网 发布:oppoa209软件下载 编辑:程序博客网 时间:2024/04/30 17:55
ViewGroup
存在的目的就是对其子View
进行管理,为其子View
添加显示、响应的规则。因此,自定义ViewGrou
p通常需要重写onMeasure()
方法对其子View
进行测量,重写onLayout()
方法来确定子View
的位置,重写onTouchEvent()
方法增加响应事件。所以我们需要做这几件事:
- 重写
onMeasure()
方法对其子View
进行测量 - 重写
onLayout()
方法来确定子View
的位置 - 重写
onTouchEvent()
方法增加响应事件
以一个粘性View
效果作为示例,来看看每部分都需要怎么做。先看完整版代码,后面会进一步分析:
package com.wondertwo.app.customview;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.Scroller;/** * 实现粘性效果,即当子View向上滑动大于某值后,松开手指它将向上滑动并显示下一个子View * 当滑动距离小于某值,松开手指后它将回到开始的位置 * * Created by wondertwo on 2016/2/27. */public class SticklyView extends ViewGroup {private int mScreenHeight;private Scroller mScroller;private int mLastY;private int mStart;private int mEnd;public SticklyView(Context context) { super(context);}public SticklyView(Context context, AttributeSet attrs) { super(context, attrs);}public SticklyView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr);}/** * 重写onMeasure()方法,通过遍历子View来测量子View的大小 * * @param widthMeasureSpec * @param heightMeasureSpec */@Overrideprotected 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); }}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); // 设置ViewGroup的高度,高度等于每个子View的高度乘以子View的个数 MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams(); mlp.height = mScreenHeight * childCount; setLayoutParams(mlp); for (int i = 0; i< childCount; i++) { View child = getChildAt(i); if (child.getVisibility() != View.GONE) { // public void layout(int left, int top, int right, int bottom)设置child的位置 child.layout(l, i * mScreenHeight, r, (i + 1) *mScreenHeight); } }}/** * 手指触摸动作的监听 * * @param event * @return */@Overridepublic 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; } if (getScrollY() > getHeight() - mScreenHeight) { dy = 0; } scrollBy(0, dy); mLastY = y; break; case MotionEvent.ACTION_UP: // 记录触摸终点 int dScrollY = checkAlignment(); 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;}@Overridepublic void computeScroll() { super.computeScroll(); if (mScroller.computeScrollOffset()) { scrollTo(0, mScroller.getCurrY()); postInvalidate(); }}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; } }}
重写
onMeasure()
方法对其子View
进行测量先要获得子View
的数量:int count = getChildCount()
。然后通过for
循环遍历每个子View
获得他们的大小。代码如下:@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {int childCount = getChildCount();// 设置ViewGroup的高度,高度等于每个子View的高度乘以子View的个数MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();mlp.height = mScreenHeight * childCount;setLayoutParams(mlp);for (int i = 0; i< childCount; i++) { View child = getChildAt(i); if (child.getVisibility() != View.GONE) { // public void layout(int left, int top, int right, int bottom)设置child的位置 child.layout(l, i * mScreenHeight, r, (i + 1) *mScreenHeight); }}}
重写
onLayout()
方法来确定子View
的位置和重写onTouchEvent()
方法增加响应事件了。其实这一步才是实现粘效果的关键。代码如下:/** * 手指触摸动作的监听 * * @param event * @return */@Overridepublic 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; } if (getScrollY() > getHeight() - mScreenHeight) { dy = 0; } scrollBy(0, dy); mLastY = y; break; case MotionEvent.ACTION_UP: // 记录触摸终点 int dScrollY = checkAlignment(); 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;}
0 0
- 【Android】Android自定义ViewGroup
- android之自定义ViewGroup
- Android中自定义ViewGroup
- android自定义View(viewGroup)
- Android中自定义ViewGroup
- Android 自定义ViewGroup
- Android 自定义ViewGroup
- Android 自定义viewgroup
- Android 自定义ViewGroup
- android--自定义ViewGroup
- Android中自定义ViewGroup
- Android 自定义ViewGroup (一)
- Android 自定义ViewGroup (二)
- Android中自定义ViewGroup
- Android自定义ViewGroup详解
- Android-自定义ViewGroup
- Android 自定义ViewGroup
- Android自定义ViewGroup
- 我活过多少天-蓝桥杯试题有感
- Codeforces Round #343 (Div. 2) D. Babaei and Birthday Cake
- property和constructor-arg的使用
- 网易公开课 计算机专业课程
- ubuntu中vim配置
- 【Android】Android自定义ViewGroup
- Java中的==与equals比较。
- broadcastreceiver
- Java学习笔记(类的可见性) http://blog.csdn.net/hawksoft/article/details/8453637
- UVA 10003 Cutting Sticks(区间dp)
- 职场新人半年工作总结
- 白话粒子群算法
- 使用NSURLSession发送HTTP请求报错
- 浅谈SSH框架