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

轻松实现 自定义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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值