本文共 5915 字,大约阅读时间需要 19 分钟。
package com.example.zxtext.diyUi;import android.content.Context;import android.content.res.Resources;import android.content.res.TypedArray;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.TypedValue;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.HorizontalScrollView;import com.example.zxtext.R;import androidx.core.view.ViewCompat;public class SlidingMenu extends HorizontalScrollView { private View mMenuView;//侧滑菜单布局 private View mContentView;//主内容界面 private int mMenuWidth;//菜单的宽度 private boolean mMenuIsOpen = false;//菜单是否打开 private GestureDetector mGestureDetector;//手势处理类,处理屏幕的手势动作 public SlidingMenu(Context context) { this(context,null); } public SlidingMenu(Context context, AttributeSet attrs) { this(context, attrs,0); } public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); float rightPadding = array.getDimension(R.styleable.SlidingMenu_SlidingMenu_rightPadding,dip2px(50)); // 计算菜单的宽度 = 屏幕的宽度 - 自定义右边留出的宽度 mMenuWidth = (int) (getScreenWidth() - rightPadding); array.recycle(); //实例化手势类 mGestureDetector = new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){ @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // 当手指快速滑动时候回调的方法 // Log.e("TAG",velocityX+""); // 如果菜单打开 并且是向左快速滑动 切换菜单的状态 if(mMenuIsOpen){ if(velocityX<-500){ toggleMenu(); return true; } }else{ // 如果菜单关闭 并且是向右快速滑动 切换菜单的状态 if(velocityX>500){ toggleMenu(); return true; } } return false; } }); } private float dip2px(int dip) { return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dip,getResources().getDisplayMetrics()); } /*而onFinishInflate方法是在setContentView之后、onMeasure之前 * Activity中调用setContentView之后就会调用onFinishInflate这个方法, * 这个方法就代表自定义控件中的子控件映射完成了,然后可以进行一些初始化控件的操作 * */ @Override protected void onFinishInflate() { super.onFinishInflate(); // 1.获取根View也就是外层的LinearLayout ViewGroup container = (ViewGroup) this.getChildAt(0); int containerChildCount = container.getChildCount(); if(containerChildCount>2){ // 里面只允许放置两个布局 一个是Menu(菜单布局) 一个是Content(主页内容布局) throw new IllegalStateException("SlidingMenu 根布局LinearLayout下面只允许两个布局,菜单布局和主页内容布局"); } // 2.获取菜单和内容布局 mMenuView = container.getChildAt(0); mContentView = container.getChildAt(1); // 3.指定内容和菜单布局的宽度 // 3.1 菜单的宽度 = 屏幕的宽度 - 自定义的右边留出的宽度 mMenuView.getLayoutParams().width = mMenuWidth; // 3.2 内容的宽度 = 屏幕的宽度 mContentView.getLayoutParams().width = getScreenWidth(); //mMenuView.setVisibility(View.GONE); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); // 布局指定后会从新摆放子布局,当其摆放完毕后,让菜单滚动到不可见状态 if (changed) { scrollTo(mMenuWidth, 0); } } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); //mMenuView.setTranslationX(l*0.8f); float scale = (1f*l)/mMenuWidth; //右边的缩放:最小是0.7f,最大是1f float rightScale = (float) (0.7f + 0.3*scale); //设置缩放的原点和大小 ViewCompat.setPivotX(mContentView,0); ViewCompat.setPivotY(mContentView,getMeasuredHeight()/2); ViewCompat.setScaleX(mContentView,rightScale); ViewCompat.setScaleY(mContentView,rightScale); //左边的缩放:最小是0.7f,最大是1f; 透明度:最小是0f,最大是1f float leftScale = (float) (1 - 0.3*scale); float alphaScale = (float) (1 - 1*scale); //设置缩放的原点和大小和透明度// ViewCompat.setPivotX(mMenuView,mMenuWidth);// ViewCompat.setPivotY(mMenuView,getMeasuredHeight()/2); ViewCompat.setScaleX(mMenuView,leftScale); ViewCompat.setScaleY(mMenuView,leftScale); ViewCompat.setAlpha(mMenuView,alphaScale); //平移,抽屉效果 ViewCompat.setTranslationX(mMenuView,l*0.3f); } /** * 获取屏幕的宽度 */ public int getScreenWidth() { Resources resources = this.getResources(); DisplayMetrics dm = resources.getDisplayMetrics(); return dm.widthPixels; } @Override public boolean onTouchEvent(MotionEvent ev) { //处理手机快速滑动 if(mGestureDetector.onTouchEvent(ev)){ return mGestureDetector.onTouchEvent(ev); } switch (ev.getAction()) { case MotionEvent.ACTION_UP: // 手指抬起获取滚动的位置 int currentScrollX = getScrollX(); if (currentScrollX > mMenuWidth / 2) { // 关闭菜单 closeMenu(); } else { // 打开菜单 openMenu(); } return false; } return super.onTouchEvent(ev); } private void openMenu() { smoothScrollTo(0,0); mMenuIsOpen = true; } private void closeMenu() { smoothScrollTo(mMenuWidth,0); mMenuIsOpen = false; } /** * 切换菜单的状态 */ private void toggleMenu() { if(mMenuIsOpen){ closeMenu(); }else{ openMenu(); } }}
转载地址:http://uhrii.baihongyu.com/