ViewPager 有很好的翻页效果,长用于图片浏览。今天产品设计了一个 奇葩的需求 ,翻页里边放tab ,并保留点击后的效果。
先看看要实现的效果, 一个两个页面的翻页效果。
实现好的效果
常用的ViewPager当然可以实现 ,但是 ViewPager 有个弊端,就是有缓存 ,使用起来也是比较麻烦。于是就想到了 scrollView。
想法: HorizontalScrollView,我们改写它的滑动事件。检测 滑动方向和距离。 当设定一个滑动距离,超过这个距离就表示翻页,没有这表示不翻页。翻页距离为一个屏幕宽度。
重点方法:
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
int scrollX = getBaseScrollX();
//左滑,大于指定距离,移到下一页
if (scrollX > mScrollX) {
baseSmoothScrollTo(mScreenWidth);
mBaseScrollX += mScreenWidth;
positionSun++;
listener.OnClickmoveItem(positionSun);
// listener.OnClickmoveItem(1);
}
//左滑,不到指定距离,返回原位
else if (scrollX > 0) {
baseSmoothScrollTo(0);
}
//右滑,不到指定距离,返回原位
else if (scrollX > -mScrollX) {
baseSmoothScrollTo(0);
}
//右滑,大于指定距离,移到下一页
else {
baseSmoothScrollTo(-mScreenWidth);
mBaseScrollX -= mScreenWidth;
positionSun--;
// listener.OnClickmoveItem(0);
listener.OnClickmoveItem(positionSun);
}
return true;
}
return super.onTouchEvent(ev);
}
完整代码代码
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
/**
* 滑动翻页效果
*/
public class PageView extends HorizontalScrollView {
private int mBaseScrollX;//滑动基线。也就是点击并滑动之前的x值,以此值计算相对滑动距离。
private int mScreenWidth;
private int mScreenHeight;
private LinearLayout mContainer;
private boolean flag;
private int mPageCount;//页面数量
private int positionSun = 0; // 记录当前位置
private int mScrollX = 100;//滑动多长距离翻页
public PageView(Context context, AttributeSet attrs) {
super(context, attrs);
DisplayMetrics dm = context.getApplicationContext().getResources()
.getDisplayMetrics();
mScreenWidth = dm.widthPixels;
mScreenHeight = dm.heightPixels;
}
/**
* 添加一个页面到最后。
*
* @param page
*/
public void addPage(View page) {
addPage(page, -1);
}
/**
* 添加一个页面。
*
* @param page
*/
public void addPage(View page, int index) {
if (!flag) {
mContainer = (LinearLayout) getChildAt(0);
flag = true;
}
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mScreenWidth, mScreenHeight);
if (index == -1) {
mContainer.addView(page, params);
} else {
mContainer.addView(page, index, params);
}
mPageCount++;
}
/**
* 移除一个页面。
*
* @param index
*/
public void removePage(int index) {
if (mPageCount < 1) {
return;
}
if (index < 0 || index > mPageCount - 1) {
return;
}
mContainer.removeViewAt(index);
mPageCount--;
}
/**
* 设置移动距离触发滑动 默认为100
*
* @param distance 水平移动的距离
*/
public void setHorizontalMovingDistance(int distance) {
if (distance != 0) {
mScrollX = distance;
}
}
/**
* 移除所有的页面
*/
public void removeAllPages() {
if (mPageCount > 0) {
mContainer.removeAllViews();
}
}
/**
* 获取页面数量
*
* @return
*/
public int getPageCount() {
return mPageCount;
}
/**
* 获取相对滑动位置。由右向左滑动,返回正值;由左向右滑动,返回负值。
*
* @return
*/
private int getBaseScrollX() {
return getScrollX() - mBaseScrollX;
}
/**
* 使相对于基线移动x距离。
*
* @param x x为正值时右移;为负值时左移。
*/
private void baseSmoothScrollTo(int x) {
smoothScrollTo(x + mBaseScrollX, 0);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
int scrollX = getBaseScrollX();
//左滑,大于指定距离,移到下一页
if (scrollX > mScrollX) {
baseSmoothScrollTo(mScreenWidth);
mBaseScrollX += mScreenWidth;
positionSun++;
listener.OnClickmoveItem(positionSun);
// listener.OnClickmoveItem(1);
}
//左滑,不到指定距离,返回原位
else if (scrollX > 0) {
baseSmoothScrollTo(0);
}
//右滑,不到指定距离,返回原位
else if (scrollX > -mScrollX) {
baseSmoothScrollTo(0);
}
//右滑,大于指定距离,移到下一页
else {
baseSmoothScrollTo(-mScreenWidth);
mBaseScrollX -= mScreenWidth;
positionSun--;
// listener.OnClickmoveItem(0);
listener.OnClickmoveItem(positionSun);
}
return true;
}
return super.onTouchEvent(ev);
}
private OnClickMove listener;
public interface OnClickMove {
// 滑动的当前位置
void OnClickmoveItem(int position);
}
// 滑动监听
public void setMoveListener(OnClickMove listener) {
this.listener = listener;
}
}
使用
//注意 里边* 必需嵌套一个子控件* ,scrollView里边只有一子空间
<com.yude.demo.views.view.PageView
android:id="@+id/pageview"
android:layout_width="wrap_content"
android:layout_height="90dp"
android:background="@color/_ffffff_bg"
android:scrollbars="none">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="horizontal">
</LinearLayout>
</com.yude.views.views.view.PageView>
activity 或 Fragment
mPageView = (PageView) rootView.findViewById(R.id.pageview);
//这里就是个普通的xml布局文件 作为第一页第二页的布局
LinearLayout view = (LinearLayout) inflater.inflate(R.layout.fragment_page1, null);
mPageView.addPage(view);
LinearLayout view2 = (LinearLayout) inflater.inflate(R.layout.fragment_page2, null);
mPageView.addPage(view2);
mPageView. setHorizontalMovingDistance(100); //设置移动距离触发滑动
mPageView.setMoveListener(new PageView.OnClickMove() {
@Override
public void OnClickmoveItem(int position) {
//设置原点视图更改 这里只有两页
Log.d("OnClickmoveItem", "当前位置" + position);
if (position == 0) {
view_0.setImageResource(dowImage[0]);
view_1.setImageResource(dowImage[1]);
} else {
view_0.setImageResource(dowImage[1]);
view_1.setImageResource(dowImage[0]);
}
}
});
实现起来还是比较简单 , 可以更具自己需要调整 。