您的位置:首页 > 其它

轻松实现 自定义slidingMenu+viewPager+scrollView

2015-11-29 16:08 465 查看

轻松实现 自定义slidingMenu+viewPager+scrollView

网上搜索了一些侧滑Menu的实现,不是太复杂就是太简单达不到一般项目需求。鉴于此,自己尝试写了一个slidingMenu,结合了viewPager并在viewPager 中内嵌了scrollView。功能上可以满足一般项目的需求,除非需要特殊的显示效果。下面我将手把手的教你如何实现。

效果图:







第一步:把需要显示的布局文件准备好

(1) Menu 文件:view_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#BDBDBD"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dip"
android:layout_marginLeft="60dip"
android:gravity="center"
android:text="Menu"
android:textColor="#030303"
android:textSize="40sp" />
<View
android:layout_width="fill_parent"
android:layout_height="0.1dip"
android:layout_marginTop="15dip"
android:layout_marginLeft="20dip"
android:background="#030303"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dip"
android:layout_marginLeft="30dip"
android:gravity="center"
android:text="menu1"
android:textColor="#030303"
android:textSize="30sp" />
</LinearLayout>


(2) content 文件:view_slide.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/slide_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff"
android:orientation="vertical">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="50dip">
<ImageView
android:id="@+id/iv_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/menu" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_centerInParent="true"
android:text="Demo"
android:textSize="30sp" />
</RelativeLayout>
<View
android:layout_width="fill_parent"
android:layout_height="0.5dip"
android:background="#C4C4C4"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="50dip">
<ImageView
android:id="@+id/iv_cursor"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_centerVertical="true"
android:src="#BBFFFF" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true">
<TextView
android:id="@+id/tv_tab_frag1"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="fragment1"
android:textSize="20sp"/>
<TextView
android:id="@+id/tv_tab_frag2"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="fragment2"
android:textSize="20sp"/>
</LinearLayout>
</RelativeLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</LinearLayout>
</LinearLayout>


(3) 主页面文件:activity_main.xml

把menu 和content 放进主页面

<?xml version="1.0" encoding="utf-8"?>
<com.example.slidingmenu_viewpager_scrollview.components.SlidingMenu xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sliding_menu"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<include layout="@layout/view_menu"/>
<include layout="@layout/view_slide"/>
</com.example.slidingmenu_viewpager_scrollview.components.SlidingMenu>


(4) 再准备两个fragment : fragment1.xml 、fragment2.xml

fragment1.xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="150dip"
android:gravity="center"
android:text="This is part 1 of fragment1"
android:textSize="30sp"/>

<TextView
android:layout_width="fill_parent"
android:layout_height="150dip"
android:layout_marginTop="500dip"
android:gravity="center"
android:text="This is part 2 of fragment1"
android:textSize="30sp"/>
</LinearLayout>
</ScrollView>
</LinearLayout>


fragment2.xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="150dip"
android:gravity="center"
android:text="This is part 1 of fragment2"
android:textSize="30sp"/>

<TextView
android:layout_width="fill_parent"
android:layout_height="150dip"
android:layout_marginTop="500dip"
android:gravity="center"
android:text="This is part 2 of fragment2"
android:textSize="30sp"/>
</LinearLayout>
</ScrollView>
</LinearLayout>


第二步:自定义slidingMenu 继承RelativeLayout

package com.example.slidingmenu_viewpager_scrollview.components;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.Scroller;

/**
* 自定义SlidingMenu;
* 实现功能:1.点击打开menu 2.内容页面 随手指移动  3.menu 打开时,内容页面任意位置点击关闭menu.
* @author zy
* 2015/11/29
*/
public class SlidingMenu extends RelativeLayout {
private static final String TAG = "SlidingMenu";
private Scroller scroller;
private View menuView;
private View slidView;
private int screenWidth;
private int menuViewWidth;
private float startX;
private float downX;
private float downY;
//slidingView scroll 的累积距离
private float scrollXDistance;
private float lastScrollX;
private boolean isMenuOpen;
//判断是否拦截touch 事件的flag
private boolean isIntercepted;
//手指移动距离小于该值时定性为点击事件,否则定性滑动事件
private static final int ONCLICK_CONDITION = 30;
//menu 代开或关闭动画时长,单位毫秒
private static final int MENU_TOGGLE_ANI_TIME = 500;

public SlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs);
scroller = new Scroller(context);
DisplayMetrics  dm = new DisplayMetrics();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(dm);
screenWidth = dm.widthPixels;
//初始化menu 宽度为700
menuViewWidth = 700;
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (changed) {
Log.i("slidingMenu", "slidingMenu");
menuView = getChildAt(0);
MarginLayoutParams menuLayoutParams = (MarginLayoutParams) menuView.getLayoutParams();
menuLayoutParams.width = menuViewWidth;
menuView.setLayoutParams(menuLayoutParams);
slidView = getChildAt(1);
MarginLayoutParams slidLayoutParams = (MarginLayoutParams) slidView.getLayoutParams();
slidLayoutParams.width = screenWidth;
slidView.setLayoutParams(slidLayoutParams);
}
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isIntercepted = false;
float x = event.getRawX();
//仅当Menu 打开,并且touch 的坐标X 在slidingView 上时才拦截事件
if(isMenuOpen && x >= menuViewWidth) {
isIntercepted = true;
return true;
}
break;
default:
break;
}
return super.onInterceptTouchEvent(event);
}

@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getRawX();
downX = startX;
downY = event.getRawY();
lastScrollX = slidView.getScrollX();
scrollXDistance = 0;
break;
case MotionEvent.ACTION_MOVE: //当手指轻触屏幕时,可能不调用ACTION_MOVE 事件
Log.i(TAG, "MotionEvent.ACTION_MOVE");
if(isIntercepted) {
float x = event.getRawX();
float deltaX = startX - x;
float curScrollX = slidView.getScrollX();
float deltaScrollX = curScrollX - lastScrollX;
//slidingView 随手指移动
if(deltaX <= -slidView.getScrollX() && deltaX >= (-slidView.getScrollX() - menuViewWidth)) {
slidView.scrollBy((int)deltaX, 0);
}
scrollXDistance += Math.abs(deltaScrollX);
lastScrollX = curScrollX;
startX = x;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if(isIntercepted) {
float upX = event.getRawX();
float upY = event.getRawY();
/*
* 判断点击事件的两个条件:1.up 与down 间距; 2.scrollX 的累积距离;
*/
if(Math.abs(upX - downX) + Math.abs(upY - downY) < ONCLICK_CONDITION
&& scrollXDistance < ONCLICK_CONDITION) {
toggle();
}else {
/*
* 当滑动距离小于menu的一半时自动回到原来位置;大于menu 一半时自动继续直至滑动完成
*/
if(Math.abs(slidView.getScrollX()) <= menuViewWidth/2) {
scroller.startScroll(slidView.getScrollX(), 0, -slidView.getScrollX() , 0,300);
isMenuOpen = false;
}else{
scroller.startScroll(slidView.getScrollX(), 0, -menuViewWidth-slidView.getScrollX(), 0,300);
isMenuOpen = true;
}
}
}
invalidate();
break;
}
return true;
}

public void toggle() {
smoothScrollTo(menuViewWidth);
}

private void smoothScrollTo(int x) {
if(isMenuOpen) {
scroller.startScroll(-x, 0, x, 0,MENU_TOGGLE_ANI_TIME);
isMenuOpen = false;
}else {
scroller.startScroll(0, 0, -x, 0,MENU_TOGGLE_ANI_TIME);
isMenuOpen = true;
}
invalidate();
}

@Override
public void computeScroll() {
if (scroller.computeScrollOffset()) {
slidView.scrollTo(scroller.getCurrX(), 0);
postInvalidate();
}
}
}


以上就是slidingMenu的所有逻辑,应该基本都能看懂。

第三步:如何使用slidingMenu

新建一个activity 继承自FragmentActivity

package com.example.slidingmenu_viewpager_scrollview.ui;

import java.util.ArrayList;
import com.example.slidingmenu_viewpager_scrollview.R;
import com.example.slidingmenu_viewpager_scrollview.components.SlidingMenu;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends FragmentActivity {
private ViewPager viewPager;
private ArrayList<Fragment> fragmentList;
private TextView tv_tab_frag1;
private TextView tv_tab_frag2;
private ImageView iv_viewPagerCursor;
private int screenWidth;
private int currentPageIndex;
private ImageView iv_menu;
private SlidingMenu slidingMenu;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
slidingMenu = (SlidingMenu)findViewById(R.id.sliding_menu);
iv_menu = (ImageView)findViewById(R.id.iv_menu);
iv_menu.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
slidingMenu.toggle();
}
});
initViewPagerTabs();
InitViewPager();
}

private void initViewPagerTabs() {
tv_tab_frag1 = (TextView)findViewById(R.id.tv_tab_frag1);
tv_tab_frag2 = (TextView)findViewById(R.id.tv_tab_frag2);
tv_tab_frag1.setOnClickListener(new tabListener(0));
tv_tab_frag2.setOnClickListener(new tabListener(1));
initViewPagerCursor();
}

private void initViewPagerCursor() {
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
screenWidth = dm.widthPixels;
iv_viewPagerCursor = (ImageView)findViewById(R.id.iv_cursor);
RelativeLayout.LayoutParams linearParams = (RelativeLayout.LayoutParams) iv_viewPagerCursor.getLayoutParams();
linearParams.width = screenWidth/2;
iv_viewPagerCursor.setLayoutParams(linearParams);
}

class tabListener implements OnClickListener{
private int index = 0;

public tabListener(int i) {
index = i;
}
@Override
public void onClick(View v) {
viewPager.setCurrentItem(index);
}
}

public void InitViewPager(){
viewPager = (ViewPager)findViewById(R.id.viewPager);
fragmentList = new ArrayList<Fragment>();
fragmentList.add(new Fragment1());
fragmentList.add(new Fragment2());
viewPager.setAdapter(new DemoFragmentPagerAdapter(getSupportFragmentManager(), fragmentList));
viewPager.setCurrentItem(0);
viewPager.setOnPageChangeListener(new DemoOnPageChangeListener());
}

private class DemoFragmentPagerAdapter extends FragmentPagerAdapter{
ArrayList<Fragment> list;
public DemoFragmentPagerAdapter(FragmentManager fm,ArrayList<Fragment> list) {
super(fm);
this.list = list;
}

@Override
public int getCount() {
return list.size();
}

@Override
public Fragment getItem(int arg0) {
return list.get(arg0);
}

}

private class DemoOnPageChangeListener implements OnPageChangeListener{

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub

}

@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub

}

@Override
public void onPageSelected(int arg0) {
Animation animation = new TranslateAnimation(currentPageIndex * screenWidth/2, arg0 * screenWidth/2,0,0);
currentPageIndex = arg0;
animation.setFillAfter(true);
animation.setDuration(200);
iv_viewPagerCursor.startAnimation(animation);
}
}
}


别忘了还有两个fragment:

Fragment1.java

package com.example.slidingmenu_viewpager_scrollview.ui;

import com.example.slidingmenu_viewpager_scrollview.R;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Fragment1 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment1, container, false);
}

}


Fragment2.java

package com.example.slidingmenu_viewpager_scrollview.ui;

import com.example.slidingmenu_viewpager_scrollview.R;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Fragment2 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment2, container, false);
}
}


OK, 到这里所有的事情就都做完了,是不是非常的easy。

源码下载地址:slidingMenu + viewPager + scrollView (GitHub)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  slidemenu viewpager