自定义View-HorizontalScrollView

2018-02-27 11:26:08来源:oschina作者:晨的暖阳人点击

分享
package com.example.chenguang.androidarttest.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;
/**
* Created by chenguang on 2018/2/12.
*/
public class HorizontalScrollView extends ViewGroup {
private Scroller mScroller;
private VelocityTracker mVelocityTracker;
private int mChildWidth;
int mChildIndex;
int mChildSize;
public HorizontalScrollView(Context context) {
this(context, null);
}
public HorizontalScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mScroller = new Scroller(getContext());
mVelocityTracker = VelocityTracker.obtain();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mChildSize = getChildCount();
//先测量所有子view的宽高
measureChildren(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width = widthSize;
int height = heightSize;
if (widthMode == MeasureSpec.AT_MOST) {//如果宽为wrap_content,width就去第一个子view打的宽度*子view个数
width = getChildAt(0).getWidth() * mChildSize;
}
if (heightMode == MeasureSpec.AT_MOST) {//如果高为wrap_content,height就取第一个子view的高度
height = getChildAt(0).getMeasuredHeight();
}
setMeasuredDimension(width, height);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childLeft = 0;
//循环布局每个子view的位置
for (int i = 0; i < mChildSize; i++) {
View childView = getChildAt(i);
if (childView.getVisibility() != View.GONE) {
mChildWidth = childView.getMeasuredWidth();
//子view按水平方向顺序排列,没有考虑自身的padding值和子view的margin值
childView.layout(childLeft, 0, childLeft + mChildWidth, childView
.getMeasuredHeight());
childLeft += mChildWidth;
}
}
}
int mLastX;
int mLastY;
@Override
public boolean onTouchEvent(MotionEvent event) {
mVelocityTracker.addMovement(event);
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
break;
case MotionEvent.ACTION_MOVE:
int dx = x - mLastX;
int dy = y - mLastY;
scrollBy(-dx, 0);
break;
case MotionEvent.ACTION_UP:
int scrollX = getScrollX();
mVelocityTracker.computeCurrentVelocity(1000);
float xVelocity = mVelocityTracker.getXVelocity();
if (Math.abs(xVelocity) > 50) {
mChildIndex = xVelocity > 0 ? mChildIndex - 1 : mChildIndex + 1;
} else {
mChildIndex = (scrollX + mChildWidth / 2) / mChildWidth;
}
mChildIndex = Math.max(0, Math.min(mChildIndex, mChildSize - 1));
dx = mChildWidth * mChildIndex - scrollX;
smoothScrollBy(dx, 0);
mVelocityTracker.clear();
break;
} mLastX = x;
mLastY = y;
return true;
}
private void smoothScrollBy(int dx, int dy) {
mScroller.startScroll(getScrollX(), dy, dx, 0, 1000);
invalidate();
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
@Override
protected void onDetachedFromWindow() {
mVelocityTracker.clear();
super.onDetachedFromWindow();
}
}

MainActivity里的activity_main.xml可以这样写:


<?xml version="1.0" encoding="utf-8"?>
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ccc">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f00"
android:gravity="center"/>
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0f0"
android:gravity="center"/>
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00f"
android:gravity="center"/>

参考:android开发艺术探索

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台