HorizontalScrollView+viewpager实现仿天天动听ios版和QQ侧边菜单效果

最近用HorizontalScrollView弄了个和slidingmenu差不多的效果的侧边菜单,顺便在里面嵌套viewpager,效果类似天天动听ios版和仿QQ侧边菜单栏,界面略戳,看图



1.    结构
最外层是一个HorizontalScrollView ,重写了它里面的一些方法从而实现划出和收起菜单的效果
里面是viewpager,能左右滑动和点击上面的文字切换。2.主要代码


</pre><pre name="code" class="html">主页布局xml和代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.have.ingeniousmusicplayer.business.workmain.view.SlidingMenu
        android:id="@+id/sm_workmain_slidingmenu"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:background="@drawable/workmain_background" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:orientation="horizontal" >

            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:background="@color/white"
                android:orientation="vertical" >

                <include layout="@layout/item_workmain_head" />

                <com.have.ingeniousmusicplayer.business.workmain.view.ViewPager
                    android:id="@+id/vp_workmain_container"
                    android:layout_width="fill_parent"
                    android:layout_height="0dp"
                    android:layout_weight="1" >
                </com.have.ingeniousmusicplayer.business.workmain.view.ViewPager>
            </LinearLayout>
            
            <include layout="@layout/layout_workmain_menu" />

        </LinearLayout>
    </com.have.ingeniousmusicplayer.business.workmain.view.SlidingMenu>

</LinearLayout>


 
<strong>
</strong>
package com.have.ingeniousmusicplayer.business.workmain;

import java.util.ArrayList;
import java.util.List;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
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.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.have.baselib.client.common.base.BaseFragmentActivity;
import com.have.ingeniousmusicplayer.MyApplication;
import com.have.ingeniousmusicplayer.R;
import com.have.ingeniousmusicplayer.business.workmain.frag.EqualizerFrag;
import com.have.ingeniousmusicplayer.business.workmain.frag.MyMusicFrag;
import com.have.ingeniousmusicplayer.business.workmain.frag.SearchFrag;
import com.have.ingeniousmusicplayer.business.workmain.frag.TransportFrag;
import com.have.ingeniousmusicplayer.business.workmain.view.SlidingMenu;
import com.have.ingeniousmusicplayer.service.QuickMenuFlowService;

/**   
 * 主页
 *
 * @author hongdameng
 * @version: [版本号, 2014-12-31] 
 * 
 */
public class WorkMainActivity extends BaseFragmentActivity implements OnClickListener {
	
	private ViewPager vp_workmain_container;
	
	private FragmentPagerAdapter fragmentPagerAdapter;
	
	private List<Fragment> fragments = new ArrayList<Fragment>();
	
	private MyMusicFrag myMusicFrag;
	
	private EqualizerFrag equalizerFrag;
	
	private SearchFrag searchFrag ;
	
	private TransportFrag transportFrag;
	
	private SlidingMenu slidingMenu;
	
	/**四个tab的容器 */
	private LinearLayout llTabContainer;
	
	private TextView tvMymusic;
	
	private TextView tvEq;
	
	private TextView tvSearch;
	
	private TextView tvTransport;
	
	private LinearLayout llMyMusic;
	
	private LinearLayout llEq;
	
	private LinearLayout llSearch;
	
	private LinearLayout llTransport;
	
	private ImageView ivMenu;
	
	private int currentIndex;

	private boolean isClickTab;

	private int tabContainerWidth;

	private View ivTabLine;
	
	private float screenWidth;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_workmain);
		initView();
		initTabLine();
		initData();
		
		initService();
	}


	private void initView() {
		llTabContainer = (LinearLayout) findViewById(R.id.ll_workmain_tab_container);
		vp_workmain_container = (ViewPager) findViewById(R.id.vp_workmain_container);
		tvMymusic = (TextView) findViewById(R.id.tv_workmain_head_tab_mymusic);
		tvEq = (TextView) findViewById(R.id.tv_workmain_head_tab_eq);
		tvSearch = (TextView) findViewById(R.id.tv_workmain_head_tab_search);
		tvTransport = (TextView) findViewById(R.id.tv_workmain_head_tab_transport);
		
		llMyMusic = (LinearLayout) findViewById(R.id.ll_workmain_head_tab_mymusic);
		llEq = (LinearLayout) findViewById(R.id.ll_workmain_head_tab_eq);
		llSearch = (LinearLayout) findViewById(R.id.ll_workmain_head_tab_search);
		llTransport = (LinearLayout) findViewById(R.id.ll_workmain_head_tab_transport);
		
		ivMenu = (ImageView) findViewById(R.id.iv_workmain_menu);
		ivMenu.setOnClickListener(this);
		llMyMusic.setOnClickListener(this);
		llEq.setOnClickListener(this);
		llSearch.setOnClickListener(this);
		llTransport.setOnClickListener(this);
		
		slidingMenu = (SlidingMenu) findViewById(R.id.sm_workmain_slidingmenu);
	}
	
	private void initData() {
		myMusicFrag = new MyMusicFrag();
		equalizerFrag = new EqualizerFrag();
		searchFrag = new SearchFrag();
		transportFrag = new TransportFrag();
		
		fragments.add(myMusicFrag);
		fragments.add(equalizerFrag);
		fragments.add(searchFrag);
		fragments.add(transportFrag);
		
		fragmentPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
			
			@Override
			public int getCount() {
				return fragments.size();
			}
			
			@Override
			public Fragment getItem(int arg0) {
				return fragments.get(arg0);
			}
		};
		
		vp_workmain_container.setAdapter(fragmentPagerAdapter);
		
		vp_workmain_container.setOnPageChangeListener(new MyOnPageChangeListener());
	}
	

	private void initService() {
//		Intent intent = new Intent(getApplicationContext(), QuickMenuFlowService.class);
//		startService(intent);
		
	}
	
	private class MyOnPageChangeListener implements OnPageChangeListener{


		@Override
		public void onPageSelected(int position) {
			resetTextColor();
			switch (position) {
			case 0:
				tvMymusic.setTextColor(getResources().getColor(
						R.color.blue_price));
				MyApplication.workmainCurrentPage = 0;
				MyApplication.isCanControlMenu = false;
				
				break;
			case 1:
				tvEq.setTextColor(getResources().getColor(
						R.color.blue_price));
				MyApplication.workmainCurrentPage = 1;
				MyApplication.isCanControlMenu = false;
				
				break;
			case 2:
				tvSearch.setTextColor(getResources().getColor(
						R.color.blue_price));
				MyApplication.workmainCurrentPage = 2;
				MyApplication.isCanControlMenu = false;
				
				break;
			case 3:
				tvTransport.setTextColor(getResources().getColor(
						R.color.blue_price));
				MyApplication.workmainCurrentPage = 3;
				
				break;
			}

			currentIndex = position;
		}

		@Override
		public void onPageScrolled(int position, float positionOffset,
				int positionOffsetPixels) {
			if (isClickTab) {
				isClickTab = false;
				return;
			}
			
			float trueOffset = positionOffset * (tabContainerWidth/screenWidth);
			
			LinearLayout.LayoutParams layoutParams = (android.widget.LinearLayout.LayoutParams) ivTabLine
					.getLayoutParams();
			if (currentIndex == 0 && position == 0) {
				layoutParams.leftMargin = (int) (trueOffset * (tabContainerWidth * 1.0 / 4) + currentIndex * (tabContainerWidth / 4)) + tabContainerWidth / 16;
				ivTabLine.setLayoutParams(layoutParams);

			} else if (currentIndex == 1 && position == 0) {  // 从位置1平移到位置0
				layoutParams.leftMargin = (int) (-(1 - trueOffset) * (tabContainerWidth * 1.0 / 4) + currentIndex * (tabContainerWidth / 4)) + tabContainerWidth / 16;
				ivTabLine.setLayoutParams(layoutParams);
			} else if(currentIndex == 1 && position == 1){
				layoutParams.leftMargin = (int) (trueOffset * (tabContainerWidth * 1.0 / 4) + currentIndex * (tabContainerWidth / 4)) + tabContainerWidth / 16;
				ivTabLine.setLayoutParams(layoutParams);
			} else if(currentIndex == 2 && position == 1){
				layoutParams.leftMargin = (int) (-(1 - trueOffset) * (tabContainerWidth * 1.0 / 4) + currentIndex * (tabContainerWidth / 4)) + tabContainerWidth / 16;
				ivTabLine.setLayoutParams(layoutParams);
			} else if(currentIndex == 2 && position == 2){
				layoutParams.leftMargin = (int) (trueOffset * (tabContainerWidth * 1.0 / 4) + currentIndex * (tabContainerWidth / 4)) + tabContainerWidth / 16;
				ivTabLine.setLayoutParams(layoutParams);
			} else if(currentIndex == 2 && position == 3){
				layoutParams.leftMargin = (int) (trueOffset * (tabContainerWidth * 1.0 / 4) + currentIndex * (tabContainerWidth / 4)) + tabContainerWidth / 16;
				ivTabLine.setLayoutParams(layoutParams);
			} else if(currentIndex == 3 && position == 2){
				layoutParams.leftMargin = (int)(-(1 - trueOffset) * (tabContainerWidth * 1.0 / 4) + currentIndex * (tabContainerWidth / 4)) + tabContainerWidth / 16;
				ivTabLine.setLayoutParams(layoutParams);
			} else if(currentIndex == 3 && position == 3){
				layoutParams.leftMargin = (int) (trueOffset * (tabContainerWidth * 1.0 / 4) + currentIndex * (tabContainerWidth / 4)) + tabContainerWidth / 16;
				ivTabLine.setLayoutParams(layoutParams);
			}
				
		}

		@Override
		public void onPageScrollStateChanged(int state) {
		}
	
	}
	
	
	
	private void initTabLine() {
		int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED); 
		int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED); 
		ivMenu.measure(w, h); 
		int menuWidth =ivMenu.getMeasuredWidth();
		
		ivTabLine = (ImageView) findViewById(R.id.iv_workmain_tabline);
		DisplayMetrics outMetrics = new DisplayMetrics();
		getWindow().getWindowManager().getDefaultDisplay()
				.getMetrics(outMetrics);
		screenWidth = outMetrics.widthPixels;
		tabContainerWidth = (int) (screenWidth  - menuWidth);
		LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) ivTabLine
				.getLayoutParams();
		lp.width = tabContainerWidth / 8;
		ivTabLine.setLayoutParams(lp);
	}
	
	/**
	 * 重置颜色
	 */
	protected void resetTextColor() {
		tvMymusic.setTextColor(getResources().getColor(R.color.gray_cccccc));
		tvEq.setTextColor(getResources().getColor(R.color.gray_cccccc));
		tvSearch.setTextColor(getResources().getColor(R.color.gray_cccccc));
		tvTransport.setTextColor(getResources().getColor(R.color.gray_cccccc));
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.iv_workmain_menu:
			slidingMenu.toggle();
			break;
		case R.id.ll_workmain_head_tab_mymusic:
			vp_workmain_container.setCurrentItem(0);
			break;
		case R.id.ll_workmain_head_tab_eq:
			vp_workmain_container.setCurrentItem(1);
			break;
		case R.id.ll_workmain_head_tab_search:
			vp_workmain_container.setCurrentItem(2);
			break;
		case R.id.ll_workmain_head_tab_transport:
			vp_workmain_container.setCurrentItem(3);
			break;
		default:
			break;
		}
	}
	
	@Override
	protected void onDestroy() {
		MyApplication.isCanControlMenu = false;
		super.onDestroy();
	}
}



重写HorizontalScrollView代码

package com.have.ingeniousmusicplayer.business.workmain.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

import com.have.ingeniousmusicplayer.MyApplication;
import com.have.ingeniousmusicplayer.common.utils.ScreenUtils;
import com.nineoldandroids.view.ViewHelper;

/**
 * <菜单侧边栏>
 * 
 * @author hongdameng
 * @version: [版本号, 2015-1-4]
 * 
 */
public class SlidingMenu extends HorizontalScrollView {

	/**
	 * 屏幕宽度
	 */
	private int mScreenWidth;
	/**
	 * dp
	 */
	private int mMenuRightPadding;
	/**
	 * 菜单的宽度
	 */
	private int mMenuWidth;
	private int mHalfMenuWidth;

	private boolean isOpen;
	
	private boolean once;

	private ViewGroup mMenu;
	private ViewGroup mContent;
	
	public SlidingMenu(Context context, AttributeSet attrs) {
		this(context, attrs, 0);

	}

	public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		mScreenWidth = ScreenUtils.getScreenWidth(context);

		mMenuRightPadding = mScreenWidth / 3;
	}

	public SlidingMenu(Context context) {
		this(context, null, 0);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		/**
		 * 显示的设置一个宽度
		 */
		if (!once) {
			LinearLayout wrapper = (LinearLayout) getChildAt(0);
			mContent = (ViewGroup) wrapper.getChildAt(0);
			mMenu = (ViewGroup) wrapper.getChildAt(1);

			mMenuWidth = mScreenWidth - mMenuRightPadding;
			mHalfMenuWidth = mMenuWidth / 2;
			mMenu.getLayoutParams().width = mMenuWidth;
			mContent.getLayoutParams().width = mScreenWidth;

		}
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);

	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if (changed) {
			// 将菜单隐藏
			this.scrollTo(0, 0);
			once = true;
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		int action = ev.getAction();
		switch (action) {
		case MotionEvent.ACTION_UP:
			int scrollX = getScrollX();
			if (scrollX > mHalfMenuWidth) {
				this.smoothScrollTo(mMenuWidth, 0);
				isOpen = true;
			} else {
				this.smoothScrollTo(0, 0);
				 MyApplication.isOpenByClick = false;
				isOpen = false;
			}
			return true;
		}
		return super.onTouchEvent(ev);
	}

	/**
	 * 打开菜单
	 */
	public void openMenu() {
		MyApplication.isOpenByClick = true;
		if (isOpen)
			return;
		this.smoothScrollTo(mMenuWidth, 0);
		isOpen = true;
	}

	/**
	 * 关闭菜单
	 */
	public void closeMenu() {
		if (isOpen) {
			this.smoothScrollTo(0, 0);
			MyApplication.isOpenByClick = false;
			isOpen = false;
		}
	}

	/**
	 * 切换菜单状态
	 */
	public void toggle() {
		if (isOpen) {
			closeMenu();
		} else {
			openMenu();
		}
	}

	@Override
	protected void onScrollChanged(int l, int t, int oldl, int oldt) {
		super.onScrollChanged(l, t, oldl, oldt);
		float scale = l * 1.0f / mMenuWidth;
		float leftScale = 1 - 0.3f * scale;
		float rightScale = 0.8f + scale * 0.2f;

		ViewHelper.setScaleX(mContent, leftScale);
		ViewHelper.setScaleY(mContent, leftScale);
		ViewHelper.setTranslationX(mContent, -mContent.getWidth() * scale * 0.01f);

		ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * scale);
		ViewHelper.setPivotX(mMenu, 0);
		ViewHelper.setPivotY(mMenu, mMenu.getHeight() / 2);
		ViewHelper.setScaleX(mMenu, rightScale);
		ViewHelper.setScaleY(mMenu, rightScale);

	}
	
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		int action = ev.getAction();
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			MyApplication.downXPosition = ev.getX();
			
		case MotionEvent.ACTION_MOVE:
			if(MyApplication.workmainCurrentPage == 3 && ev.getX() > MyApplication.downXPosition && ! isOpen){
				MyApplication.isCanControlMenu = false;
			}
		}
		
		return super.onInterceptTouchEvent(ev) && (MyApplication.isCanControlMenu || MyApplication.isOpenByClick);
	}
	
}



重写 viewpager 代码

/*  
 * 文件名:     ViewPager.java 
 * 文件描述: ()
 * 修改人:     [hongdameng] 
 * 生成时间:  2015-1-5 下午1:56:59 
 * 修改记录:
 */
package com.have.ingeniousmusicplayer.business.workmain.view;

import com.have.ingeniousmusicplayer.MyApplication;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;

/**
 * <首页viewpager>
 * 
 * @author hongdameng
 * @version: [版本号, 2015-1-5]
 * 
 */
public class ViewPager extends android.support.v4.view.ViewPager {

	public ViewPager(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			MyApplication.downXPosition = ev.getX();
			return super.onTouchEvent(ev);
		case MotionEvent.ACTION_MOVE:
			if (this.getCurrentItem() == 3 && MyApplication.downXPosition > ev.getX()) {
				MyApplication.isCanControlMenu = true;
				return super.onTouchEvent(ev);
			} else {
				return super.onTouchEvent(ev);
			}

		default:
			return super.onTouchEvent(ev);
		}
	}

}
</pre><pre name="code" class="html">

为了在页面切换过程中判断是否要打开菜单,我在application保存了一些状态

public class MyApplication extends BaseApplication {
	public static int workmainCurrentPage = 0;
	
	public static boolean isCanControlMenu = false;
	
	public static float downXPosition = 0;
	
	public static boolean isOpenByClick = false;
	
	@Override
	public void onCreate() {
		super.onCreate();
		
		initService();
	}

	/** 
	 * 初始化服务
	 */
	private void initService() {
		//TODO
		workmainCurrentPage = 0; //可以通过读取 SharedPreferences 设置当前页
	}
}

1. 原理

重写HorizontalScrollView ,实现划出和收起菜单和QQ类似的效果,在用户滑动再抬起手的时候判断露出菜单的偏移量来打开或者关闭菜单,在viewpager滑动过程中,如果是滑到最后一页,再向左滑动机打开菜单,里面的状态都是通过application保存着。



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值