本篇文章主要写的是ViewPager+一个侧滑菜单,其实这个用SlideMeun实现更好,但是那毕竟不是自己写的控件,所以我就尝试着自己写一个控件了,由于自己是个新手,技术不怎么样,所以控件写的不够好,但是胜在简单、明了,希望能给同样是新手的朋友带来一丝灵感,好了下面我开始顺着代码讲解吧!
这就是我实现后的效果,左边是Viewpager,右边是一个Layout
下边我贴上代码
首先是整体的xml布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<--这里是我自定义的一个Layout,在里面处理手势冲突问题-->
<com.example.horizontalviewpager.view.ViewPagerLy
android:id="@+id/horizon_vp_ly"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00ff00"
/>
</com.example.horizontalviewpager.view.ViewPagerLy>
<--这是 右侧的菜单栏-->
<LinearLayout
android:id="@+id/right_ly"
android:layout_width="140dip"
android:layout_height="match_parent"
android:background="#000000"
android:orientation="vertical"
android:gravity="center"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
/>
</LinearLayout>
</RelativeLayout>
com.example.horizontalviewpager.view.ViewPagerLy这是我的自定义的类,在里面对手势做过处理,
避免与横向滑动的ViewPager有冲突,下面的这个LinearLayout,是右侧的侧滑菜单,我会在代码中对它
的位置进行调整;
OK!接下来我将放上我的java代码:
这是我自定义的类,用于解决手势冲突:
package com.example.horizontalviewpager.view;
import com.example.horizontalviewpager.MainActivity.OnInterceptListener;
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.widget.LinearLayout;
public class ViewPagerLy extends LinearLayout{
private GestureDetector mGestureDetector;
//回调接口对象
private OnHorizontalScrollListener mOnScrollListenerCallback = null;
private boolean iscanScroll;
private int mScrollX = 0;
private OnInterceptListener mListener;
private boolean bTouchIntercept = false;
public ViewPagerLy(Context context) {
this(context,null);
}
public ViewPagerLy(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(new HorizontalScrollGestureListener());
}
//对回调接口设值
public void setOnInterceptListenr(OnInterceptListener listener){
mListener = listener;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
bTouchIntercept = mGestureDetector.onTouchEvent(ev);
if(MotionEvent.ACTION_UP == ev.getAction()){ // 监听抬手动作
if(mOnScrollListenerCallback != null){
mOnScrollListenerCallback.doOnRelease(); // 抬手后对做出回弹效果
}
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return bTouchIntercept;
}
//回调接口赋值
public void setonHorizontalScrollListener(OnHorizontalScrollListener l){
this.mOnScrollListenerCallback = l;
}
//在这里解决手势冲突问题
private class HorizontalScrollGestureListener extends SimpleOnGestureListener{
//如果iscanScroll为真,则消费,否则不消费
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
mScrollX += distanceX;
int flag = mListener.isIntercept(); //调用回调接口,并获取 条件返回值(flag)
System.out.println("ViewPagerLy.flag:"+flag+",,distanceX:" + distanceX);
if ( flag == 0 || (flag == 1 && distanceX>0)) {
if(mOnScrollListenerCallback != null) {
mOnScrollListenerCallback.doOnScroll(e1, e2, distanceX, distanceY);
}
return true;
}else {
return false;
}
}
@Override
public boolean onDown(MotionEvent e) {
return super.onDown(e);
}
}
public interface OnHorizontalScrollListener {//回调接口
public void doOnScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
public void doOnRelease();
}
}
上面这个类主要逻辑放在OnHorizontalScrollListener这个回调接口上,在外部实现这个接口来确定滚动事件
还有一个OnInterceptListener 接口,用来判断现在是否需要拦截手势;
package com.example.horizontalviewpager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import com.example.horizontalviewpager.view.MyVpAdapter;
import com.example.horizontalviewpager.view.ViewPagerLy;
import com.example.horizontalviewpager.view.ViewPagerLy.OnHorizontalScrollListener;
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private ViewPager vp;
/**
* 自定义中linear
*/
private ViewPagerLy vpLy;
/**
* 右边的linear
*/
private LinearLayout rightLy;
/**
* 滚动距离
*/
private int mScroll;
private boolean isConsumed = false;
private boolean isFirst = true;
private final int SPEED = 10;
void initView() {
vpLy = (ViewPagerLy) findViewById(R.id.horizon_vp_ly);
rightLy = (LinearLayout) findViewById(R.id.right_ly);
vp = (ViewPager) findViewById(R.id.viewpager_id);
vp.setAdapter(new MyVpAdapter(getSupportFragmentManager()));
vp.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
vpLy.setonHorizontalScrollListener(new OnHorizontalScrollListener() {
@Override
public void doOnScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
onScroll(distanceX);
}
@Override
public void doOnRelease() {
onRelease();
}
});
resizeLayout();
vpLy.setOnInterceptListenr(new OnInterceptListener() {
@Override
public int isIntercept() {
RelativeLayout.LayoutParams lp = (LayoutParams) vpLy.getLayoutParams();
if (vp.getCurrentItem() == 2) { //判断ViewPager的当前页面是否为最后一个页面(我的一共3个所以偷懒写死了)
System.out.println(lp.leftMargin+":sfasdfgasd");
if (lp.leftMargin!=0) {
return 0;
}else if (lp.leftMargin == 0) {
return 1;
}else {
return 2;
}
}else {
return 2;
}
}
});
}
private void resizeLayout() { //将布局重新摆放
DisplayMetrics dm = getResources().getDisplayMetrics();
// 固定 main layout, 防止被左、右挤压变形
RelativeLayout.LayoutParams lp = (LayoutParams) vpLy.getLayoutParams();
lp.width = dm.widthPixels;
vpLy.setLayoutParams(lp);
// 将右layout调整至main layout右边
lp = (LayoutParams) rightLy.getLayoutParams();
lp.leftMargin = dm.widthPixels;
lp.rightMargin = -lp.width;
rightLy.setLayoutParams(lp);
}
private void rollLayout(int margin) {
RelativeLayout.LayoutParams lp = (LayoutParams) vpLy.getLayoutParams();
lp.leftMargin += margin;
lp.rightMargin -= margin;
vpLy.setLayoutParams(lp);
lp = (LayoutParams) rightLy.getLayoutParams();
lp.leftMargin += margin;
rightLy.setLayoutParams(lp);
}
void onScroll(float distanceX) {
mScroll += distanceX;// 向左为正
RelativeLayout.LayoutParams lp = (LayoutParams) vpLy.getLayoutParams();
RelativeLayout.LayoutParams lpRight = (LayoutParams) rightLy
.getLayoutParams();
int distance = 0;
if (mScroll > 0) {//向左移动,打开右侧菜单的过程
distance = lpRight.width - Math.abs(lp.leftMargin);
if (distance <0) {
distance = 0;
}
if (mScroll >= distance) {
mScroll = distance;
}
} else if (mScroll <= 0) {//向右移动,关闭右侧菜单的过程
distance = lp.leftMargin;
if (distance >= 0) {
mScroll = 0;
}
}
if (distanceX != 0) {
rollLayout(-mScroll);
}
}
void onRelease() {
RelativeLayout.LayoutParams lp = (LayoutParams) vpLy
.getLayoutParams();
if (lp.leftMargin < 0) { // 左移
/*
* 左移大于右导航宽度一半,则自动展开,否则自动缩回去
*/
if (Math.abs(lp.leftMargin) > rightLy.getLayoutParams().width / 2) {
new SlideMenu().execute(rightLy.getLayoutParams().width
- Math.abs(lp.leftMargin), -SPEED);
} else {
new SlideMenu().execute(Math.abs(lp.leftMargin), SPEED);
}
} else if (lp.leftMargin > 0) {
/*
* 右移大于左导航宽度一半,则自动展开,否则自动缩回去
*/
if (Math.abs(lp.leftMargin) > rightLy.getLayoutParams().width / 2) {
new SlideMenu().execute(rightLy.getLayoutParams().width
- Math.abs(lp.leftMargin), SPEED);
} else {
new SlideMenu().execute(Math.abs(lp.leftMargin), -SPEED);
}
}
}
public class SlideMenu extends AsyncTask<Integer, Integer, Void> {
@Override
protected Void doInBackground(Integer... params) {
if (params.length != 2) {
}
int times = params[0] / Math.abs(params[1]);
if (params[0] % Math.abs(params[1]) != 0) {
times++;
}
for (int i = 0; i < times; i++) {
this.publishProgress(params[0], params[1], i + 1);
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
if (values.length != 3) {
}
int distance = Math.abs(values[1]) * values[2];
int delta = values[0] - distance;
int leftMargin = 0;
if (values[1] < 0) { // 左移
leftMargin = (delta > 0 ? values[1]
: -(Math.abs(values[1]) - Math.abs(delta)));
} else {
leftMargin = (delta > 0 ? values[1]
: (Math.abs(values[1]) - Math.abs(delta)));
}
rollLayout(leftMargin);
}
}
public interface OnInterceptListener{
public int isIntercept();
}
}
OnInterceptListener接口类,返回状态值,判断手势是否拦截;SlideMenu 类实现回弹效果
package com.example.horizontalviewpager.view;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.example.horizontalviewpager.R;
public class FragmentItem extends Fragment{
int mNum;
public static FragmentItem newInstance(int num) {
FragmentItem f = new FragmentItem();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
mNum = getArguments() != null ? getArguments().getInt("num") : 1;
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.item_ly, container, false);
TextView text = (TextView)v.findViewById(R.id.text_id);
text.setText("第"+mNum+"页");
return v;
}
}
OK!还有几个类没有上传,我会把源码放到网上的