轻松实现 自定义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 继承自FragmentActivitypackage 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)
相关文章推荐
- 使用ViewPager实现高仿launcher左右拖动效果
- Android 使用 ViewPager循环广告位的实现
- 实现轮转广告带底部指示的自定义ViewPager控件
- 自定义RadioButton和ViewPager实现TabHost带滑动的页卡效果
- Android基于ViewPager Fragment实现选项卡
- 使用ViewPager实现android软件使用向导功能实现步骤
- Android编程ViewPager回弹效果实例分析
- Android 使用ViewPager自动滚动循环轮播效果
- Android ViewPager相册横向移动的实现方法
- Android 使用viewpager实现无限循环(定时+手动)
- Android编程实现ListView头部ViewPager广告轮询图效果
- Android 利用ViewPager实现图片可以左右循环滑动效果附代码下载
- Android编程开发ScrollView中ViewPager无法正常滑动问题解决方法
- viewpager的layout_width="wrap_content"无效问题
- ScrollView ViewPager嵌套导致滑动冲突解决方案
- Fragment+viewpager+Fragment 嵌套 第二次进入该fragment不显示数据
- android自定义tabbar,并带badgeview消息提示
- ViewPager播放图片问题
- CollapsingAvatarToolbar 头像随ListView滚动缩回到ActionBar特
- Material-Movies-master 影视软件封面页面呈现