viewpager 禁用滑到两边的颜色

与listview不同的是:fadeingedge=none即可。

viewpager则更加复杂一点。

先看下ViewPager中和这个颜色相关的代码:


private EdgeEffectCompat mLeftEdge;

private EdgeEffectCompat mRightEdge;

就是这俩货,导致的边界颜色。没办法,这货是private的,后面只能通过反射来得到了。

再看下draw()方法中的逻辑:


@Override

public void draw(Canvas canvas) {

super.draw(canvas);

boolean needsInvalidate = false;

final int overScrollMode = ViewCompat.getOverScrollMode(this);

if (overScrollMode == ViewCompat.OVER_SCROLL_ALWAYS ||

(overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS &&

mAdapter != null && mAdapter.getCount() > 1)) {

if (!mLeftEdge.isFinished()) {

final int restoreCount = canvas.save();

final int height = getHeight() - getPaddingTop() - getPaddingBottom();

canvas.rotate(270);

canvas.translate(-height + getPaddingTop(), 0);

mLeftEdge.setSize(height, getWidth());

needsInvalidate |= mLeftEdge.draw(canvas);

canvas.restoreToCount(restoreCount);

}

if (!mRightEdge.isFinished()) {

final int restoreCount = canvas.save();

final int width = getWidth();

final int height = getHeight() - getPaddingTop() - getPaddingBottom();

final int itemCount = mAdapter != null ? mAdapter.getCount() : 1;

canvas.rotate(90);

canvas.translate(-getPaddingTop(),

-itemCount * (width + mPageMargin) + mPageMargin);

mRightEdge.setSize(height, width);

needsInvalidate |= mRightEdge.draw(canvas);

canvas.restoreToCount(restoreCount);

}

} else {

mLeftEdge.finish();

mRightEdge.finish();

}

if (needsInvalidate) {

// Keep animating

invalidate();

}

}

在进行绘制渐变图片之前会判断是否已经finish,【if (!mLeftEdge.isFinished())】,如果我们能修改为finished状态,不就OK了吗?!经过测试,调用mLeftEdge.finish()和mRightEdge.finish()就能达到我们要的结果。但是悲催的是,draw()方法是随时随地都在调用的,所以要在一个在draw()方法之后调用,但是还得随时随地调用的方法才行。

好吧,先说点原理的东东。

ViewPager.javaàdraw()方法 à mRightEdge.draw(canvas);以及mLeftEdge.draw(canvas);à EdgeEffectCompat.javaà看下全部的代码吧:


public class EdgeEffectCompat {

private Object mEdgeEffect;

private static final EdgeEffectImpl IMPL;

static {

if (Build.VERSION.SDK_INT >= 14) { // ICS

IMPL = new EdgeEffectIcsImpl();

} else {

IMPL = new BaseEdgeEffectImpl();

}

}

interface EdgeEffectImpl {

public Object newEdgeEffect(Context context);

public void setSize(Object edgeEffect, int width, int height);

public boolean isFinished(Object edgeEffect);

public void finish(Object edgeEffect);

public boolean onPull(Object edgeEffect, float deltaDistance);

public boolean onRelease(Object edgeEffect);

public boolean onAbsorb(Object edgeEffect, int velocity);

public boolean draw(Object edgeEffect, Canvas canvas);

}

/**

* Null implementation to use pre-ICS

*/

static class BaseEdgeEffectImpl implements EdgeEffectImpl {

public Object newEdgeEffect(Context context) {

return null;

}

public void setSize(Object edgeEffect, int width, int height) {

}

public boolean isFinished(Object edgeEffect) {

return true;

}

public void finish(Object edgeEffect) {

}

public boolean onPull(Object edgeEffect, float deltaDistance) {

return false;

}

public boolean onRelease(Object edgeEffect) {

return false;

}

public boolean onAbsorb(Object edgeEffect, int velocity) {

return false;

}

public boolean draw(Object edgeEffect, Canvas canvas) {

return false;

}

}

static class EdgeEffectIcsImpl implements EdgeEffectImpl {

public Object newEdgeEffect(Context context) {

return EdgeEffectCompatIcs.newEdgeEffect(context);

}

public void setSize(Object edgeEffect, int width, int height) {

EdgeEffectCompatIcs.setSize(edgeEffect, width, height);

}

public boolean isFinished(Object edgeEffect) {

return EdgeEffectCompatIcs.isFinished(edgeEffect);

}

public void finish(Object edgeEffect) {

EdgeEffectCompatIcs.finish(edgeEffect);

}

public boolean onPull(Object edgeEffect, float deltaDistance) {

return EdgeEffectCompatIcs.onPull(edgeEffect, deltaDistance);

}

public boolean onRelease(Object edgeEffect) {

return EdgeEffectCompatIcs.onRelease(edgeEffect);

}

public boolean onAbsorb(Object edgeEffect, int velocity) {

return EdgeEffectCompatIcs.onAbsorb(edgeEffect, velocity);

}

public boolean draw(Object edgeEffect, Canvas canvas) {

return EdgeEffectCompatIcs.draw(edgeEffect, canvas);

}

}

/**

* Construct a new EdgeEffect themed using the given context.

*

* <p>Note: On platform versions that do not support EdgeEffect, all operations

* on the newly constructed object will be mocked/no-ops.</p>

*

* @param context Context to use for theming the effect

*/

public EdgeEffectCompat(Context context) {

mEdgeEffect = IMPL.newEdgeEffect(context);

}

/**

* Set the size of this edge effect in pixels.

*

* @param width Effect width in pixels

* @param height Effect height in pixels

*/

public void setSize(int width, int height) {

IMPL.setSize(mEdgeEffect, width, height);

}

/**

* Reports if this EdgeEffectCompat‘s animation is finished. If this method returns false

* after a call to {@link #draw(Canvas)} the host widget should schedule another

* drawing pass to continue the animation.

*

* @return true if animation is finished, false if drawing should continue on the next frame.

*/

public boolean isFinished() {

return IMPL.isFinished(mEdgeEffect);

}

/**

* Immediately finish the current animation.

* After this call {@link #isFinished()} will return true.

*/

public void finish() {

IMPL.finish(mEdgeEffect);

}

/**

* A view should call this when content is pulled away from an edge by the user.

* This will update the state of the current visual effect and its associated animation.

* The host view should always {@link android.view.View#invalidate()} if this method

* returns true and draw the results accordingly.

*

* @param deltaDistance Change in distance since the last call. Values may be 0 (no change) to

* 1.f (full length of the view) or negative values to express change

* back toward the edge reached to initiate the effect.

* @return true if the host view should call invalidate, false if it should not.

*/

public boolean onPull(float deltaDistance) {

return IMPL.onPull(mEdgeEffect, deltaDistance);

}

/**

* Call when the object is released after being pulled.

* This will begin the "decay" phase of the effect. After calling this method

* the host view should {@link android.view.View#invalidate()} if this method

* returns true and thereby draw the results accordingly.

*

* @return true if the host view should invalidate, false if it should not.

*/

public boolean onRelease() {

return IMPL.onRelease(mEdgeEffect);

}

/**

* Call when the effect absorbs an impact at the given velocity.

* Used when a fling reaches the scroll boundary.

*

* <p>When using a {@link android.widget.Scroller} or {@link android.widget.OverScroller},

* the method <code>getCurrVelocity</code> will provide a reasonable approximation

* to use here.</p>

*

* @param velocity Velocity at impact in pixels per second.

* @return true if the host view should invalidate, false if it should not.

*/

public boolean onAbsorb(int velocity) {

return IMPL.onAbsorb(mEdgeEffect, velocity);

}

/**

* Draw into the provided canvas. Assumes that the canvas has been rotated

* accordingly and the size has been set. The effect will be drawn the full

* width of X=0 to X=width, beginning from Y=0 and extending to some factor <

* 1.f of height.

*

* @param canvas Canvas to draw into

* @return true if drawing should continue beyond this frame to continue the

* animation

*/

public boolean draw(Canvas canvas) {

return IMPL.draw(mEdgeEffect, canvas);

}

}

à看完之后,下面进入到EdgeEffectCompatIcs.javaà好吧,再贴上完整的代码


class EdgeEffectCompatIcs {

public static Object newEdgeEffect(Context context) {

return new EdgeEffect(context);

}

public static void setSize(Object edgeEffect, int width, int height) {

((EdgeEffect) edgeEffect).setSize(width, height);

}

public static boolean isFinished(Object edgeEffect) {

return ((EdgeEffect) edgeEffect).isFinished();

}

public static void finish(Object edgeEffect) {

((EdgeEffect) edgeEffect).finish();

}

public static boolean onPull(Object edgeEffect, float deltaDistance) {

((EdgeEffect) edgeEffect).onPull(deltaDistance);

return true;

}

public static boolean onRelease(Object edgeEffect) {

EdgeEffect eff = (EdgeEffect) edgeEffect;

eff.onRelease();

return eff.isFinished();

}

public static boolean onAbsorb(Object edgeEffect, int velocity) {

((EdgeEffect) edgeEffect).onAbsorb(velocity);

return true;

}

public static boolean draw(Object edgeEffect, Canvas canvas) {

return ((EdgeEffect) edgeEffect).draw(canvas);

}

}

à下面进入到EdgeEffect.java中吧à如果你有闲情逸致的话,那就看下他的代码吧,都是这货在搞鬼。

下面就说正经的内容了,看看我的解决方案:

主要是在自定义的OnPageChangeListener里面。

先定义一下:


private EdgeEffectCompat leftEdge;

private EdgeEffectCompat rightEdge;

然后是构造中,通过反射得到对象:


try {

Field leftEdgeField = mViewPager.getClass().getDeclaredField("mLeftEdge");

Field rightEdgeField = mViewPager.getClass().getDeclaredField("mRightEdge");

Log.i("xinye", "=======leftEdgeField:" + leftEdgeField + ",rightEdgeField:" + rightEdgeField);

if(leftEdgeField != null && rightEdgeField != null){

leftEdgeField.setAccessible(true);

rightEdgeField.setAccessible(true);

leftEdge = (EdgeEffectCompat) leftEdgeField.get(mViewPager);

rightEdge = (EdgeEffectCompat) rightEdgeField.get(mViewPager);

Log.i("xinye", "=======OK啦,leftEdge:" + leftEdge + ",rightEdge:" + rightEdge);

}

} catch (Exception e) {

e.printStackTrace();

}

然后,就是最重要的了:


@Override

public void onPageScrolled(int position, floatpositionOffset, int positionOffsetPixels){

if(leftEdge != null && rightEdge != null){

leftEdge.finish();

rightEdge.finish();

leftEdge.setSize(0, 0);

rightEdge.setSize(0, 0);

}

时间: 2024-11-03 03:34:26

viewpager 禁用滑到两边的颜色的相关文章

ViewPager 嵌套Listview 让Listview响应 ViewPager 左右滑事件

一段拦截判断而已.   之前一直误解了一个拦截的描述.导致搞了半天. 结论: onInterceptTouchEvent 返回true,就由本身View的onTouchEvent进行事件消费. /** 在控件中 左右滑时 强制拦截事件的ViewPager * Created by user on 2016/3/7. */ public class MyViewPager extends ViewPager { private String TAG = "MyViewPager"; pr

android Viewpager禁用/开启滑动切换功能

要实现viewpager的滑动以及禁止滑动切换功能只需要继承viewpager,在onTouchEvent进行逻辑判断即可(网上搜到的,确实可行,原创地址不明),下面自己实现一个 public class MyViewPager extends ViewPager { private boolean scrollble=true; public MyViewPager super(context); } public MyViewPager(Context context, AttributeS

ViewPager实现滑屏的无限循环

实现ViewPager无限循环: 1.让ViewPager的PagerAdapter无限大且内容重复 2.实现自动滚屏控制器 上源码: 1 /** 2 * ViewPager无限循环实现 3 * 1.实现一个无限大的PagerAdapter 4 * 2.继承ViewPager重写setAdapter方法 5 * 3.实现一个自动滚屏的控制器 6 * 注意:数据刷新调用LoopViewPager类里的notifyDataSetChanged 7 * @author sdsw 8 * 9 */ 10

android:修改PagerTabStrip中的背景颜色,标题字体的样式、颜色和图标以及指示条的颜色

1.修改PagerTabStrip中的背景颜色 我们在布局中直接设置background属性即可: <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="fill_parent" android:layout_height="fill_parent" > <android.support.v4.view.PagerTabS

【Android】ViewPager实现无限循环滚动

最近做的一个项目,客户要求在ViewPager实现的主页面中滑动到最后一页后继续滑动能返回到第一页,也就是实现无限循环滚动,效果如下: 看了下ViewPager没有滑到尽头的回调方法,因此想到的解决方案是,在原来的最后一页之后再加上一个第一页,也就是原本有编号为a1,b,c的三个页面,现在在最后面再加一个a页面,变为a1.b.c.a2四个页面,然后使用OnPageChangeListener中的onPageSelected方法来监听到页面切换,当发现是从第三个页面(c)切换到第四个页面(a1)时

Android——ViewPager和内部view之间的事件分发及轮播图

viewpager 在滑动的过程中是如何触发view身上的事件的,换句话说,viewpager在滑动的过程中到底是滑动的它里面的view,还是滑动的viewpager本身? 一.示例代码: 1.自定义ViewPager:MyViewPager,重新dispatchTouchEvent方法,添加一些事件处理的log信息. package com.example.viewpagerdemo; import android.content.Context; import android.support

android:更改PagerTabStrip背景颜色,标题字体样式、颜色和图标,以及指示条的颜色

1.更改PagerTabStrip背景颜色 我们直接在布局中设置background属性可以: <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="fill_parent" android:layout_height="fill_parent" > <android.support.v4.view.PagerTabStr

Android_字体变色,viewpager指示器

简介 本篇是来自鸿洋_大神的Android 自定义控件玩转字体变色 打造炫酷ViewPager指示器这篇博客,刚开始看时觉得不是很好理解,现在自己减去了他的一些代码,自己写的一个,也实现了同样的效果,感觉好理解多了. 先看一下实现后的效果: 要实现这样的文字跟随viewpager的滑动而逐渐改变颜色的效果,这里很明显底色字一直在的,所以我们要考虑的主要是红色字体的绘制.绘制红色字体用的是canvas的clipRect()方法.根据要改变的宽度系数,切割要绘制的位置.这里运用了自定义属性,方便我们

iOS UITableView左滑操作功能的实现(iOS8-11)

WeTest 导读 本文主要是介绍下iOS 11系统及iOS 11之前的系统在实现左滑操作功能上的区别,及如何自定义左滑的标题颜色.字体大小. 一.左滑操作功能实现 1.如果左滑的时候只有一个操作按钮,可以使用如下三个delegate方法来实现: 2.如果左滑有一个或多个操作按钮,iOS8-10 可使用如下两个delegate 3.iOS 11之后,tableView的delegate增加了两个方法,用来取代editActionsForRowAtIndexPath方法,如下: 在2和3中,如果是