实现ViewPager一次滑动多页(保持居中)
项目中开发日历功能,需求是可以连续滑动多页,有列表的流畅。又要保持当前页居中显示。
参考文献: http://www.open-open.com/lib/view/open1435026935638.html
http://mp.weixin.qq.com/s/DMksgHOuGWhztESGfDgucA?utm_source=tuicool&utm_medium=referral
效果图:
1. 继承自RecyclerView的ViewPager:
/** * Created by Administrator on 2017/6/9. * 基于RecyclerView实现的ViewPager,支持类似于gallary的fling操作 * http://www.open-open.com/lib/view/open1435026935638.html */public class RecyclerViewPager extends RecyclerView { public static final boolean DEBUG = BuildConfig.DEBUG; private RecyclerViewPagerAdapter<?> mViewPagerAdapter; private float mTriggerOffset = 0.25f; private float mFlingFactor = 0.15f; private float mMillisecondsPerInch = 25f; private float mTouchSpan; private List<OnPageChangedListener> mOnPageChangedListeners; private int mSmoothScrollTargetPosition = -1; private int mPositionBeforeScroll = -1; private boolean mSinglePageFling; boolean isInertia; // inertia slide state float minSlideDistance; PointF touchStartPoint; boolean mNeedAdjust; int mFisrtLeftWhenDragging; int mFirstTopWhenDragging; View mCurView; int mMaxLeftWhenDragging = Integer.MIN_VALUE; int mMinLeftWhenDragging = Integer.MAX_VALUE; int mMaxTopWhenDragging = Integer.MIN_VALUE; int mMinTopWhenDragging = Integer.MAX_VALUE; private int mPositionOnTouchDown = -1; private boolean mHasCalledOnPageChanged = true; private boolean reverseLayout = false; private float mLastY; public RecyclerViewPager(Context context) { this(context, null); } public RecyclerViewPager(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RecyclerViewPager(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initAttrs(context, attrs, defStyle); setNestedScrollingEnabled(false); ViewConfiguration viewConfiguration = ViewConfiguration.get(context); minSlideDistance = viewConfiguration.getScaledTouchSlop(); } private void initAttrs(Context context, AttributeSet attrs, int defStyle) { final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecyclerViewPager, defStyle, 0); mFlingFactor = a.getFloat(R.styleable.RecyclerViewPager_rvp_flingFactor, 0.15f); mTriggerOffset = a.getFloat(R.styleable.RecyclerViewPager_rvp_triggerOffset, 0.25f); mSinglePageFling = a.getBoolean(R.styleable.RecyclerViewPager_rvp_singlePageFling, mSinglePageFling); isInertia = a.getBoolean(R.styleable.RecyclerViewPager_rvp_inertia, false); mMillisecondsPerInch = a.getFloat(R.styleable.RecyclerViewPager_rvp_millisecondsPerInch, 25f); a.recycle(); } public void setFlingFactor(float flingFactor) { mFlingFactor = flingFactor; } public float getFlingFactor() { return mFlingFactor; } public void setTriggerOffset(float triggerOffset) { mTriggerOffset = triggerOffset; } public float getTriggerOffset() { return mTriggerOffset; } public void setSinglePageFling(boolean singlePageFling) { mSinglePageFling = singlePageFling; } public boolean isSinglePageFling() { return mSinglePageFling; } public boolean isInertia() { return isInertia; } public void setInertia(boolean inertia) { isInertia = inertia; } @Override protected void onRestoreInstanceState(Parcelable state) { try { Field fLayoutState = state.getClass().getDeclaredField("mLayoutState"); fLayoutState.setAccessible(true); Object layoutState = fLayoutState.get(state); Field fAnchorOffset = layoutState.getClass().getDeclaredField("mAnchorOffset"); Field fAnchorPosition = layoutState.getClass().getDeclaredField("mAnchorPosition"); fAnchorPosition.setAccessible(true); fAnchorOffset.setAccessible(true); if (fAnchorOffset.getInt(layoutState) > 0) { fAnchorPosition.set(layoutState, fAnchorPosition.getInt(layoutState) - 1); } else if (fAnchorOffset.getInt(layoutState) < 0) { fAnchorPosition.set(layoutState, fAnchorPosition.getInt(layoutState) + 1); } fAnchorOffset.setInt(layoutState, 0); } catch (Throwable e) { e.printStackTrace(); } super.onRestoreInstanceState(state); } @Override public void setAdapter(Adapter adapter) { mViewPagerAdapter = ensureRecyclerViewPagerAdapter(adapter); super.setAdapter(mViewPagerAdapter); } @Override public void swapAdapter(Adapter adapter, boolean removeAndRecycleExistingViews) { mViewPagerAdapter = ensureRecyclerViewPagerAdapter(adapter); super.swapAdapter(mViewPagerAdapter, removeAndRecycleExistingViews); } @Override public Adapter getAdapter() { if (mViewPagerAdapter != null) { return mViewPagerAdapter.mAdapter; } return null; } public RecyclerViewPagerAdapter getWrapperAdapter() { return mViewPagerAdapter; } @Override public void setLayoutManager(LayoutManager layout) { super.setLayoutManager(layout); if (layout instanceof LinearLayoutManager) { reverseLayout = ((LinearLayoutManager) layout).getReverseLayout(); } } @Override public boolean fling(int velocityX, int velocityY) { boolean flinging = super.fling((int) (velocityX * mFlingFactor), (int) (velocityY * mFlingFactor)); if (flinging) { if (getLayoutManager().canScrollHorizontally()) { adjustPositionX(velocityX); } else { adjustPositionY(velocityY); } } if (DEBUG) { Log.d("@", "velocityX:" + velocityX); Log.d("@", "velocityY:" + velocityY); } return flinging; } @Override public void smoothScrollToPosition(int position) { if (DEBUG) { Log.d("@", "smoothScrollToPosition:" + position); } if (mPositionBeforeScroll < 0) { mPositionBeforeScroll = getCurrentPosition(); } mSmoothScrollTargetPosition = position; if (getLayoutManager() != null && getLayoutManager() instanceof LinearLayoutManager) { // exclude item decoration LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(getContext()) { @Override public PointF computeScrollVectorForPosition(int targetPosition) { if (getLayoutManager() == null) { return null; } return ((LinearLayoutManager) getLayoutManager()) .computeScrollVectorForPosition(targetPosition); } @Override protected void onTargetFound(View targetView, RecyclerView.State state, Action action) { if (getLayoutManager() == null) { return; } int dx = calculateDxToMakeVisible(targetView, getHorizontalSnapPreference()); int dy = calculateDyToMakeVisible(targetView, getVerticalSnapPreference()); if (dx > 0) { dx = dx - getLayoutManager() .getLeftDecorationWidth(targetView); } else { dx = dx + getLayoutManager() .getRightDecorationWidth(targetView); } if (dy > 0) { dy = dy - getLayoutManager() .getTopDecorationHeight(targetView); } else { dy = dy + getLayoutManager() .getBottomDecorationHeight(targetView); } final int distance = (int) Math.sqrt(dx * dx + dy * dy); final int time = calculateTimeForDeceleration(distance); if (time > 0) { action.update(-dx, -dy, time, mDecelerateInterpolator); } } @Override protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { return mMillisecondsPerInch / displayMetrics.densityDpi; } @Override protected void onStop() { super.onStop(); if (mOnPageChangedListeners != null) { for (OnPageChangedListener onPageChangedListener : mOnPageChangedListeners) { if (onPageChangedListener != null) { onPageChangedListener.OnPageChanged(mPositionBeforeScroll, mSmoothScrollTargetPosition); } } } mHasCalledOnPageChanged = true; } }; linearSmoothScroller.setTargetPosition(position); if (position == RecyclerView.NO_POSITION) { return; } getLayoutManager().startSmoothScroll(linearSmoothScroller); } else { super.smoothScrollToPosition(position); } } @Override public void scrollToPosition(int position) { if (DEBUG) { Log.d("@", "scrollToPosition:" + position); } mPositionBeforeScroll = getCurrentPosition(); mSmoothScrollTargetPosition = position; super.scrollToPosition(position); getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @SuppressWarnings("deprecation") @Override public void onGlobalLayout() { if (Build.VERSION.SDK_INT < 16) { getViewTreeObserver().removeGlobalOnLayoutListener(this); } else { getViewTreeObserver().removeOnGlobalLayoutListener(this); } if (mSmoothScrollTargetPosition >= 0 && mSmoothScrollTargetPosition < getItemCount()) { if (mOnPageChangedListeners != null) { for (OnPageChangedListener onPageChangedListener : mOnPageChangedListeners) { if (onPageChangedListener != null) { onPageChangedListener.OnPageChanged(mPositionBeforeScroll, getCurrentPosition()); } } } } } }); } private int getItemCount() { return mViewPagerAdapter == null ? 0 : mViewPagerAdapter.getItemCount(); } /** * get item position in center of viewpager */ public int getCurrentPosition() { int curPosition; if (getLayoutManager().canScrollHorizontally()) { curPosition = RecycleViewPagerUtils.getCenterXChildPosition(this); } else { curPosition = RecycleViewPagerUtils.getCenterYChildPosition(this); } if (curPosition < 0) { curPosition = mSmoothScrollTargetPosition; } return curPosition; } /*** * adjust position before Touch event complete and fling action start. */ protected void adjustPositionX(int velocityX) { if (reverseLayout) velocityX *= -1; int childCount = getChildCount(); if (childCount > 0) { int curPosition = RecycleViewPagerUtils.getCenterXChildPosition(this); int childWidth = getWidth() - getPaddingLeft() - getPaddingRight(); int flingCount = getFlingCount(velocityX, childWidth); int targetPosition = curPosition + flingCount; if (mSinglePageFling) { flingCount = Math.max(-1, Math.min(1, flingCount)); targetPosition = flingCount == 0 ? curPosition : mPositionOnTouchDown + flingCount; if (DEBUG) { Log.d("@", "flingCount:" + flingCount); Log.d("@", "original targetPosition:" + targetPosition); } } targetPosition = Math.max(targetPosition, 0); targetPosition = Math.min(targetPosition, getItemCount() - 1); if (targetPosition == curPosition && (!mSinglePageFling || mPositionOnTouchDown == curPosition)) { View centerXChild = RecycleViewPagerUtils.getCenterXChild(this); if (centerXChild != null) { if (mTouchSpan > centerXChild.getWidth() * mTriggerOffset * mTriggerOffset && targetPosition != 0) { if (!reverseLayout) targetPosition--; else targetPosition++; } else if (mTouchSpan < centerXChild.getWidth() * -mTriggerOffset && targetPosition != getItemCount() - 1) { if (!reverseLayout) targetPosition++; else targetPosition--; } } } if (DEBUG) { Log.d("@", "mTouchSpan:" + mTouchSpan); Log.d("@", "adjustPositionX:" + targetPosition); } smoothScrollToPosition(safeTargetPosition(targetPosition, getItemCount())); } } public void addOnPageChangedListener(OnPageChangedListener listener) { if (mOnPageChangedListeners == null) { mOnPageChangedListeners = new ArrayList<>(); } mOnPageChangedListeners.add(listener); } public void removeOnPageChangedListener(OnPageChangedListener listener) { if (mOnPageChangedListeners != null) { mOnPageChangedListeners.remove(listener); } } public void clearOnPageChangedListeners() { if (mOnPageChangedListeners != null) { mOnPageChangedListeners.clear(); } } /*** * adjust position before Touch event complete and fling action start. */ protected void adjustPositionY(int velocityY) { if (reverseLayout) velocityY *= -1; int childCount = getChildCount(); if (childCount > 0) { int curPosition = RecycleViewPagerUtils.getCenterYChildPosition(this); int childHeight = getHeight() - getPaddingTop() - getPaddingBottom(); int flingCount = getFlingCount(velocityY, childHeight); int targetPosition = curPosition + flingCount; if (mSinglePageFling) { flingCount = Math.max(-1, Math.min(1, flingCount)); targetPosition = flingCount == 0 ? curPosition : mPositionOnTouchDown + flingCount; } targetPosition = Math.max(targetPosition, 0); targetPosition = Math.min(targetPosition, getItemCount() - 1); if (targetPosition == curPosition && (!mSinglePageFling || mPositionOnTouchDown == curPosition)) { View centerYChild = RecycleViewPagerUtils.getCenterYChild(this); if (centerYChild != null) { if (mTouchSpan > centerYChild.getHeight() * mTriggerOffset && targetPosition != 0) { if (!reverseLayout) targetPosition--; else targetPosition++; } else if (mTouchSpan < centerYChild.getHeight() * -mTriggerOffset && targetPosition != getItemCount() - 1) { if (!reverseLayout) targetPosition++; else targetPosition--; } } } if (DEBUG) { Log.d("@", "mTouchSpan:" + mTouchSpan); Log.d("@", "adjustPositionY:" + targetPosition); } smoothScrollToPosition(safeTargetPosition(targetPosition, getItemCount())); } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN && getLayoutManager() != null) { mPositionOnTouchDown = getLayoutManager().canScrollHorizontally() ? RecycleViewPagerUtils.getCenterXChildPosition(this) : RecycleViewPagerUtils.getCenterYChildPosition(this); if (DEBUG) { Log.d("@", "mPositionOnTouchDown:" + mPositionOnTouchDown); } mLastY = ev.getRawY(); } return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent e) { // recording the max/min value in touch track if (e.getAction() == MotionEvent.ACTION_MOVE) { if (mCurView != null) { mMaxLeftWhenDragging = Math.max(mCurView.getLeft(), mMaxLeftWhenDragging); mMaxTopWhenDragging = Math.max(mCurView.getTop(), mMaxTopWhenDragging); mMinLeftWhenDragging = Math.min(mCurView.getLeft(), mMinLeftWhenDragging); mMinTopWhenDragging = Math.min(mCurView.getTop(), mMinTopWhenDragging); } } return super.onTouchEvent(e); } @Override public boolean onInterceptTouchEvent(MotionEvent e) { if (isInertia) { final float x = e.getRawX(); final float y = e.getRawY(); if (touchStartPoint == null) touchStartPoint = new PointF(); switch (MotionEvent.ACTION_MASK & e.getAction()) { case MotionEvent.ACTION_DOWN: touchStartPoint.set(x, y); break; case MotionEvent.ACTION_MOVE: float tempDistance = (float) Math.sqrt(x*x+ y*y); float lastDistance = (float) Math.sqrt(touchStartPoint.x*touchStartPoint.x + touchStartPoint.y*touchStartPoint.y); if (Math.abs(lastDistance - tempDistance) > minSlideDistance) { float k = Math.abs((touchStartPoint.y - y) / (touchStartPoint.x - x)); // prevent tan 90° calc if (Math.abs(touchStartPoint.y - y) < 1) return getLayoutManager().canScrollHorizontally(); if (Math.abs(touchStartPoint.x - x) < 1) return !getLayoutManager().canScrollHorizontally(); return k < Math.tan(Math.toRadians(30F)); } break; } } return super.onInterceptTouchEvent(e); } @Override public void onScrollStateChanged(int state) { super.onScrollStateChanged(state); if (state == SCROLL_STATE_DRAGGING) { mNeedAdjust = true; mCurView = getLayoutManager().canScrollHorizontally() ? RecycleViewPagerUtils.getCenterXChild(this) : RecycleViewPagerUtils.getCenterYChild(this); if (mCurView != null) { if (mHasCalledOnPageChanged) { // While rvp is scrolling, mPositionBeforeScroll will be previous value. mPositionBeforeScroll = getChildLayoutPosition(mCurView); mHasCalledOnPageChanged = false; } if (DEBUG) { Log.d("@", "mPositionBeforeScroll:" + mPositionBeforeScroll); } mFisrtLeftWhenDragging = mCurView.getLeft(); mFirstTopWhenDragging = mCurView.getTop(); } else { mPositionBeforeScroll = -1; } mTouchSpan = 0; } else if (state == SCROLL_STATE_SETTLING) { mNeedAdjust = false; if (mCurView != null) { if (getLayoutManager().canScrollHorizontally()) { mTouchSpan = mCurView.getLeft() - mFisrtLeftWhenDragging; } else { mTouchSpan = mCurView.getTop() - mFirstTopWhenDragging; } } else { mTouchSpan = 0; } mCurView = null; } else if (state == SCROLL_STATE_IDLE) { if (mNeedAdjust) { int targetPosition = getLayoutManager().canScrollHorizontally() ? RecycleViewPagerUtils.getCenterXChildPosition(this) : RecycleViewPagerUtils.getCenterYChildPosition(this); if (mCurView != null) { targetPosition = getChildAdapterPosition(mCurView); if (getLayoutManager().canScrollHorizontally()) { int spanX = mCurView.getLeft() - mFisrtLeftWhenDragging; // if user is tending to cancel paging action, don't perform position changing if (spanX > mCurView.getWidth() * mTriggerOffset && mCurView.getLeft() >= mMaxLeftWhenDragging) { if (!reverseLayout) targetPosition--; else targetPosition++; } else if (spanX < mCurView.getWidth() * -mTriggerOffset && mCurView.getLeft() <= mMinLeftWhenDragging) { if (!reverseLayout) targetPosition++; else targetPosition--; } } else { int spanY = mCurView.getTop() - mFirstTopWhenDragging; if (spanY > mCurView.getHeight() * mTriggerOffset && mCurView.getTop() >= mMaxTopWhenDragging) { if (!reverseLayout) targetPosition--; else targetPosition++; } else if (spanY < mCurView.getHeight() * -mTriggerOffset && mCurView.getTop() <= mMinTopWhenDragging) { if (!reverseLayout) targetPosition++; else targetPosition--; } } } smoothScrollToPosition(safeTargetPosition(targetPosition, getItemCount())); mCurView = null; } else if (mSmoothScrollTargetPosition != mPositionBeforeScroll) { if (DEBUG) { Log.d("@", "onPageChanged:" + mSmoothScrollTargetPosition); } mPositionBeforeScroll = mSmoothScrollTargetPosition; } // reset mMaxLeftWhenDragging = Integer.MIN_VALUE; mMinLeftWhenDragging = Integer.MAX_VALUE; mMaxTopWhenDragging = Integer.MIN_VALUE; mMinTopWhenDragging = Integer.MAX_VALUE; } } @SuppressWarnings("unchecked") @NonNull protected RecyclerViewPagerAdapter ensureRecyclerViewPagerAdapter(Adapter adapter) { return (adapter instanceof RecyclerViewPagerAdapter) ? (RecyclerViewPagerAdapter) adapter : new RecyclerViewPagerAdapter(this, adapter); } private int getFlingCount(int velocity, int cellSize) { if (velocity == 0) { return 0; } int sign = velocity > 0 ? 1 : -1; return (int) (sign * Math.ceil((velocity * sign * mFlingFactor / cellSize) - mTriggerOffset)); } private int safeTargetPosition(int position, int count) { if (position < 0) { return 0; } if (position >= count) { return count - 1; } return position; } public interface OnPageChangedListener { /** * Fires when viewpager changes it's page * @param oldPosition old position * @param newPosition new position */ void OnPageChanged(int oldPosition, int newPosition); } public float getlLastY() { return mLastY; }}
2.xml文件调用:
<你的包名.calender.activity.RecyclerViewPager android:id="@+id/calender_pager" android:layout_marginTop="10dp" android:layout_marginBottom="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="50dp" android:paddingRight="50dp" android:paddingStart="40dp" android:paddingEnd="40dp" app:rvp_triggerOffset="0.1" app:rvp_singlePageFling="false" android:clipToPadding="false"/>3.代码调用:
RecyclerViewPager calenderPager= (RecyclerViewPager) head.findViewById(R.id.calender_pager);
LinearLayoutManager layout = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); calenderPager.setLayoutManager(layout); pagerAdapter = new LayoutAdapter(this,calenderDataList); calenderPager.setAdapter(pagerAdapter); calenderPager.setHasFixedSize(true); calenderPager.setLongClickable(true); calenderPager.setSinglePageFling(false); calenderPager.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int scrollState) {// updateState(scrollState); } @Override public void onScrolled(RecyclerView recyclerView, int i, int i2) { int childCount = calenderPager.getChildCount(); int width = calenderPager.getChildAt(0).getWidth(); int padding = (calenderPager.getWidth() - width) / 2; for (int j = 0; j < childCount; j++) { View v = recyclerView.getChildAt(j); //往左 从 padding 到 -(v.getWidth()-padding) 的过程中,由大到小 float rate = 0; ; if (v.getLeft() <= padding) { if (v.getLeft() >= padding - v.getWidth()) { rate = (padding - v.getLeft()) * 1f / v.getWidth(); } else { rate = 1; } v.setScaleY(1 - rate * 0.1f); v.setScaleX(1 - rate * 0.1f); } else { //往右 从 padding 到 recyclerView.getWidth()-padding 的过程中,由大到小 if (v.getLeft() <= recyclerView.getWidth() - padding) { rate = (recyclerView.getWidth() - padding - v.getLeft()) * 1f / v.getWidth(); } v.setScaleY(0.9f + rate * 0.1f); v.setScaleX(0.9f + rate * 0.1f); } } } }); calenderPager.addOnPageChangedListener(new RecyclerViewPager.OnPageChangedListener() { @Override public void OnPageChanged(int oldPosition, int newPosition) { if (currentMonth==newPosition){//第一次进入, return; } if (oldPosition==newPosition){//没有滑动出当前item return; } currentMonth=newPosition; //刷新绑定状态 updatMarkerButton(); //刷新事件列表 //旧数据清除 List list= adapter.getData(); if (list.size()>0) { for (int i = 0; i < calenderDataList.get(oldPosition).getData().size(); i++) { adapter.notifyItemRemoved(i+1); } list.clear(); adapter.notifyItemRangeRemoved(1, calenderDataList.get(oldPosition).getData().size() - 2); } //新数据插入 List<CalenderDayBean> newList=calenderDataList.get(newPosition).getData(); for (int i = 0; i < newList.size(); i++) { dayList.add(newList.get(i)); adapter.notifyItemInserted(1); adapter.notifyItemRangeChanged(1, newList.size()-2); } } }); calenderPager.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { if (calenderPager.getChildCount() < 3) { if (calenderPager.getChildAt(1) != null) { if (calenderPager.getCurrentPosition() == 0) { View v1 = calenderPager.getChildAt(1); v1.setScaleY(0.9f); v1.setScaleX(0.9f); } else { View v1 = calenderPager.getChildAt(0); v1.setScaleY(0.9f); v1.setScaleX(0.9f); } } } else { if (calenderPager.getChildAt(0) != null) { View v0 = calenderPager.getChildAt(0); v0.setScaleY(0.9f); v0.setScaleX(0.9f); } if (calenderPager.getChildAt(2) != null) { View v2 = calenderPager.getChildAt(2); v2.setScaleY(0.9f); v2.setScaleX(0.9f); } } } }); calenderPager.scrollToPosition(currentMonth); }
转载于:https://www.cnblogs.com/donghaifeng-2016/p/7115997.html
实现ViewPager一次滑动多页(保持居中)相关推荐
- ViewPager + Fragment实现滑动标签页
ViewPager 结合Fragment实现一个Activity里包含多个可滑动的标签页,每个标签页可以有独立的布局及响应. activity_main.xml [html] view plainco ...
- ViewPager实现滑动翻页效果
实现ViewPager的滑动翻页效果可以使用ViewPager的setPageTransformer方法,如下: import android.content.Context; import andr ...
- android控件翻书效果,android ViewPager实现滑动翻页效果实例代码
实现ViewPager的滑动翻页效果可以使用ViewPager的setPageTransformer方法,如下:import android.content.Context;import androi ...
- android 翻书动画效果怎么做,android ViewPager实现滑动翻页效果实例代码
实现ViewPager的滑动翻页效果可以使用ViewPager的setPageTransformer方法,如下: import android.content.Context; import andr ...
- ViewPager和Fragment实现滑动标签页步骤以及方法总结
要实现左右滑动的标签页其实有很多种办法,比如最外层一个FrameLayout,里面重叠几个View监听滑动事件来控制具体的展示效果以及相应的处理,还有其他很多种方式,但是呢各个方法的运行效率以及编码速 ...
- android viewpager 上下滚动条,安卓中使用ViewPager2实现上下滑动翻页
目标 实现上下滑动翻页,类似于抖音.快手短视频的操作方式. 实现方案 添加依赖 implementation "androidx.viewpager2:viewpager2:1.0.0&qu ...
- android ViewPager页面左右滑动切换
我们日常生活中用到的微博,QQ,微信等app在进行页面左右滑动的时候,很多都可以用ViewPager来实现.可以说,ViewPager在android开发中十分常见并且特别实用. Viewpager在 ...
- android fragment界面滑动切换效果,Android App中使用ViewPager+Fragment实现滑动切换效果...
在android应用中,多屏滑动是一种很常见的风格,没有采用viewpager的代码实现会很长,如果采用ViewPager,代码就会短很多,但是使用ViewPager也有弊端:需要导入android- ...
- 程序猿媛:滑动翻页+区域点击事件
Android GridView 滑动翻页+区域点击事件 如有转载,请保留原文地址:"http://www.cnblogs.com/LuoYer/p/3409988.html",谢 ...
最新文章
- 浅析redis与zookeeper构建分布式锁的异同
- apache java windows_Apache for Windows 安装
- 短信验证码、图形验证码、邮件验证的自动化测试
- python后端服务器_毕设里配合Python后端使用的所谓”CGI服务器“
- SpringMVC 中xml 配置多数据源
- 最少预算覆盖最多应用,高性价比小企业服务器服务器榜单
- 第17课:基于 CRF 的中文句法依存分析模型实现
- 第六次作业(C语言)
- c++的assert函数
- 开源开放 | 欢迎选修浙江大学《知识图谱》开放共享慕课
- intellij idea如何打包
- android os苹果手机助手,深度系统V20(1003)内测招募:新增手机助手,支持安卓/iOS端...
- python是什么-Python 简介
- mysql isamchk_mysqlcheck与myisamchk的区别
- 你觉得jQuery源码中有哪些写得好的地方?
- Android源码下载(包括最新8.0版本)
- 计算机的com端口万能驱动,USB转串口万能驱动
- java jmail_jmail和javamail的区别
- ​依图上市,AI 四小龙走向「三岔路口」
- K650c + Ubuntu15.04双显卡切换
热门文章
- java注解获取参数_JAVA 自定义注解及参数获取 | 学步园
- javascript继承的原理
- java for循环效率优化_java 优雅代码for循环 之性能调优
- 本科、硕士、博士的区别
- 游戏社交不足怎么办? 游戏发行中的社交化运营经验分享
- mysql_fetch_array详解
- 使用Box2D制作AS3游戏——2.1a版本——Hello World Box2D .
- 5.2.1 标准原子类型
- 【每日一题】Leetcode 刷题 二叉树-树的遍历 介绍
- java调用c 返回值_推荐--Linux平台下Java调用C函数(补充关于String类型函数返回值)...