自定义布局实现左右或者上下翻页效果(借助Scroller类)
2016-10-21 21:23
393 查看
以下代码大部分借鉴于郭神的博客:Android Scroller完全解析,关于Scroller你所需知道的一切 我在这个基础上面增加了上下翻页的效果,逻辑其实没什么改动。
先上效果图
![](http://img.blog.csdn.net/20161021211021364)
![](http://img.blog.csdn.net/20161021211247987)
下面是稍微修改后的代码,注释在代码里写的比较详细了:
其中自定义了一个属性支持在布局文件中切换横向or纵向滚动,属性文件如下:
Activity的布局文件:
Activity中不用做任何操作,即可看到效果:
小伙伴们快去试试吧…
先上效果图
下面是稍微修改后的代码,注释在代码里写的比较详细了:
public class ScrollerLayout extends ViewGroup { private final String TAG = "ScrollerLayout"; /** * 用于滚动的实例对象 */ private Scroller mScroller; /** * 判定为拖动的最小移动像素数 */ private int mTouchSlop; /** * 手指按下是事的x坐标 */ private float mXDown; /** * 手指触摸时的位置 */ private float mXMove; /** * 上次手指移动时的位置 */ private float mXLastMove; //视图可移动的左边界 private int leftBorder; //视图可移动的最大右边界 private int rightBorder; /** * 手指按下是事的y坐标 */ private float mYDown; /** * 手指触摸时的位置 */ private float mYMove; /** * 上次手指移动时的位置 */ private float mYLastMove; //视图可移动的上边界 private int topBorder; //视图可移动的最大下边界 private int bottomBorder; //翻页方向(左右 or 上下) private int direction; public ScrollerLayout(Context context) { this(context, null); } public ScrollerLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ScrollerLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mScroller = new Scroller(getContext()); ViewConfiguration configuration = ViewConfiguration.get(getContext()); mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ScrollerLayout, defStyleAttr, 0); direction = ta.getInt(R.styleable.ScrollerLayout_direction, 1); ta.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); measureChild(childView, widthMeasureSpec, heightMeasureSpec); } } //摆放所有子view) @Override protected void onLayout(boolean b, int i, int i1, int i2, int i3) { int childCount = getChildCount(); if (b) { for (int j = 0; j < childCount; j++) { View childView = getChildAt(j); //左上右下(横向摆放) if (direction == 1) { childView.layout(j * childView.getMeasuredWidth(), 0, childView.getMeasuredWidth() * (j + 1), childView.getMeasuredHeight()); } else { //左上右下(纵向摆放) childView.layout(0, j * childView.getMeasuredHeight(), childView.getMeasuredWidth(), childView.getMeasuredHeight() * (j + 1)); } } leftBorder = getChildAt(0).getLeft(); //0 rightBorder = getChildAt(childCount - 1).getRight(); //页数*页面宽度 topBorder = getChildAt(0).getTop(); //0 bottomBorder = getChildAt(childCount - 1).getBottom(); //页数*页面高度 Log.d(TAG, "topBorder:" + topBorder + " ,bottomBorder:" + bottomBorder); Log.d(TAG, "leftBorder:" + leftBorder + " ,rightBorder:" + rightBorder); } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mXDown = ev.getRawX(); mXLastMove = mXDown; mYDown = ev.getRawY(); mYLastMove = mYDown; break; case MotionEvent.ACTION_MOVE: mXMove = ev.getRawX(); mXLastMove = mXMove; mYMove = ev.getRawY(); mYLastMove = mYMove; //滑动了多少距离 float diff; if (direction == 1) { diff = Math.abs(mXMove - mXDown); } else { diff = Math.abs(mYMove - mYDown); } //滚动其实是父控件的滚动 // 当手指拖动值大于TouchSlop值时,认为应该进行滚动,拦截子控件的事件 if (diff > mTouchSlop) { return true; } break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: mXMove = event.getRawX(); mYMove = event.getRawY(); if (direction == 1) { //移动了多少距离 向左滑动时值为正数,向右滑动时值为负数 int scrolledX = (int) (mXLastMove - mXMove); Log.d(TAG, "onMove:" + getScrollX() + " ,scrolledX:" + scrolledX); //此判断只针对向右滑动时(即第一页就向右滑动) if (getScrollX() + scrolledX < leftBorder) { scrollTo(leftBorder, 0); Toast.makeText(getContext(), "已经是第一页啦", 100).show(); return true; } //此判断只针对最后一页向左滑动时 //最后一页时getScrollX() = (页数-1)* screenWidth,向左滑动时scrollX大于0 else if (getScrollX() + getWidth() + scrolledX > rightBorder) { scrollTo(rightBorder - getWidth(), 0); Toast.makeText(getContext(), "已经是最后一页啦", 100).show(); return true; } scrollBy(scrolledX, 0); } else { //移动了多少距离 向上滑动时值为正数,向下滑动时值为负数 int scrolledY = (int) (mYLastMove - mYMove); Log.d(TAG, "onMove:" + getScrollY() + " ,scrolledY:" + scrolledY); //此判断只针对向右滑动时(即第一页就向下滑动)0 + 负数 if (getScrollY() + scrolledY < topBorder) { //判定为第一页时向下滑动 scrollTo(0, topBorder); Toast.makeText(getContext(), "已经是顶部啦", 100).show(); return true; } //此判断只针对最后一页向上滑动时 //getHeight为当前整个可见页面的高度 //最后一页时getScrollY() = (页数-1)* screenHeight,向上滑动时scrollY大于0 else if (getScrollY() + getHeight() + scrolledY > bottomBorder) { scrollTo(0, bottomBorder - getHeight()); Toast.makeText(getContext(), "已经是底部啦", 100).show(); return true; } scrollBy(0, scrolledY); } mXLastMove = mXMove; mYLastMove = mYMove; break; case MotionEvent.ACTION_UP: if (direction == 1) { // 当手指抬起时,根据当前的滚动值来判定应该滚动到哪个子控件的界面 int targetIndex = (getScrollX() + getWidth() / 2) / getWidth(); int dx = targetIndex * getWidth() - getScrollX(); // 第二步,调用startScroll()方法来初始化滚动数据并刷新界面 // (起始点的x坐标,起始点的y坐标,终点x坐标,终点y坐标) mScroller.startScroll(getScrollX(), 0, dx, 0); } else { int targetIndex = (getScrollY() + getHeight() / 2) / getHeight(); int dy = targetIndex * getHeight() - getScrollY(); mScroller.startScroll(0, getScrollY(), 0, dy); } invalidate(); //必须调用该方法 break; } return super.onTouchEvent(event); } @Override public void computeScroll() { //super.computeScroll(); // 第三步,重写computeScroll()方法,并在其内部完成平滑滚动的逻辑 if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } } }
其中自定义了一个属性支持在布局文件中切换横向or纵向滚动,属性文件如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="ScrollerLayout"> <attr name="direction"> <enum name="horizontal" value="1" /> <enum name="vertical" value="2" /> </attr> </declare-styleable> </resources>
Activity的布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <com.hanson.scrollerdemo.view.ScrollerLayout android:layout_width="match_parent" android:layout_height="match_parent" app:direction="horizontal"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/darker_gray" android:clickable="true" android:focusable="true" android:focusableInTouchMode="true" android:gravity="center" android:text="页面一" android:textColor="#ffffff" /> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/holo_red_light" android:clickable="true" android:focusable="true" android:focusableInTouchMode="true" android:gravity="center" android:text="页面二" android:textColor="@android:color/white" /> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/holo_green_light" android:clickable="true" android:focusable="true" android:focusableInTouchMode="true" android:gravity="center" android:text="页面三" android:textColor="@android:color/white" /> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/holo_blue_light" android:clickable="true" android:focusable="true" android:focusableInTouchMode="true" android:gravity="center" android:text="页面四" android:textColor="@android:color/white" /> </com.hanson.scrollerdemo.view.ScrollerLayout> </LinearLayout>
Activity中不用做任何操作,即可看到效果:
public class MainActivity extends AppCompatActivity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); } }
小伙伴们快去试试吧…
相关文章推荐
- android之实现上下左右翻页效果
- js实现移动端手指左右上下滑动翻页效果
- 采用Scroller实现任意布局的上下左右弹性效果
- Android自定义左右或上下滑动翻页效果
- 使用viewpager嵌套实现上下左右滑动切换图片(IOS双向滚动翻页效果相同)
- 布局动画Android ScrollView HorizontalScrollView 实现全方向(上下左右)反弹效果
- 采用Scroller实现任意布局的上下左右弹性效果
- android之实现上下左右翻页效果
- 使用viewpager嵌套实现上下左右滑动切换图片(IOS双向滚动翻页效果相同)
- 布局demo三:viewPager实现翻页效果
- 可滑动控件(ListView,WebView,ScrollView)实现弹性滑动或者取消弹性滑动(上下或左右滑动)
- android 实现左右上下震动的效果
- 三种布局实现上下回弹效果(普通布局,ListView,ScrollView)
- jquery实现图片上下左右翻滚效果代码
- 实现android布局的左右拖动及动画效果的代码范例
- android自定义布局-ScrollLayout 实现左右滑动
- UITableView中识别左右滑动,实现上下翻页的功能
- Android ScrollView HorizontalScrollView 实现全方向(上下左右)反弹效果
- 用javascript实现以个动画效果(可以上下左右的移动)
- 自定义button,实现图片和文字上下排列,左右排列等等