带有侧滑菜单的ViewPager

本篇文章主要写的是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!还有几个类没有上传,我会把源码放到网上的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值