基于Android实现仿QQ5.0侧滑

本课程将带领大家通过自定义控件实现QQ5.0侧滑菜单,课程将循序渐进,首先实现最普通的侧滑菜单,然后引入属性动画与拖动菜单效果相结合,最终实现QQ5.0侧滑菜单效果。通过本课程大家会对侧滑菜单有更深层次的了解,通过自定义控件和属性动画打造千变万化的侧滑菜单效果

效果图如下所示:

基于Android实现仿QQ5.0侧滑_第1张图片基于Android实现仿QQ5.0侧滑_第2张图片

package com.example;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
public class MainActivity extends ActionBarActivity {
  private SlidingMenu mMenu;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mMenu = (SlidingMenu) findViewById(R.id.id_menu);
  }
  public void toggleMenu(View view)
  {
    mMenu.toggle();
  }
} 
package com.example;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.WindowManager;
/**
 * Created by tuhao-pc on 2015/12/28.
 * 获取屏幕相关的辅助类
 */
public class ScreenUtils {
  private ScreenUtils() {
  }
  /**
   *获取屏幕的高度
   * @param context
   * @return
   */
  public static int getScreenWidth(Context context){
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics outMetrics = new DisplayMetrics();
    wm.getDefaultDisplay().getMetrics(outMetrics);
    return outMetrics.widthPixels;
  }
  /**
   * 获取屏幕的高度
   * @param context
   * @return
   */
  public static int getScreenHeight(Context context){
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics outMetrics = new DisplayMetrics();
    wm.getDefaultDisplay().getMetrics(outMetrics);
    return outMetrics.heightPixels;
  }
  /**
   * 获取手机状态栏的状态
   * @param context
   * @return
   */
  public static int getStatusHeight(Context context){
    int statusHeight = -1;
    Class clazz = null;
    try {
      clazz = Class.forName("com.android.internal.R$dimen");
      Object object = clazz.newInstance();
      int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString());
      statusHeight = context.getResources().getDimensionPixelSize(height);
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    } catch (NoSuchFieldException e) {
      e.printStackTrace();
    } catch (InstantiationException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    }
    return statusHeight;
  }
  /**
   * 获取当前屏幕截图,包含状态栏
   *
   * @param activity
   * @return
   */
  public static Bitmap snapShotWithStatusBar(Activity activity)
  {
    View view = activity.getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    Bitmap bmp = view.getDrawingCache();
    int width = getScreenWidth(activity);
    int height = getScreenHeight(activity);
    Bitmap bp = null;
    bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
    view.destroyDrawingCache();
    return bp;
  }
  /**
   * 获取当前屏幕截图,不包含状态栏
   *
   * @param activity
   * @return
   */
  public static Bitmap snapShotWithoutStatusBar(Activity activity)
  {
    View view = activity.getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    Bitmap bmp = view.getDrawingCache();
    Rect frame = new Rect();
    activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
    int statusBarHeight = frame.top;
    int width = getScreenWidth(activity);
    int height = getScreenHeight(activity);
    Bitmap bp = null;
    bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
        - statusBarHeight);
    view.destroyDrawingCache();
    return bp;
  }
} 
package com.example;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import com.nineoldandroids.view.ViewHelper;
/**
 * Created by tuhao-pc on 2015/12/28.
 */
public class SlidingMenu extends HorizontalScrollView{
  private int mScreenWidth;
  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) {
    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);
    mScreenWidth = ScreenUtils.getScreenWidth(context);
    TypedArray a = context.getTheme().obtainStyledAttributes(attrs,R.styleable.SlidingMenu,defStyleAttr,0);
    int count = a.getIndexCount();
    for(int i = 0;i < count;i++){
      int attr = a.getIndex(i);
      switch (attr){
        case R.styleable.SlidingMenu_rightPadding:{
//          默认是50
          mMenuRightPadding = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,50f,getResources().getDisplayMetrics()));
          break;
        }
      }
    }
    a.recycle();
  }
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    /**
     * 显示设置一个宽度
     */
    if(!once){
      LinearLayout wrapper = (LinearLayout) getChildAt(0);
      mMenu = (ViewGroup) wrapper.getChildAt(0);
      mContent = (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(mMenuWidth, 0);
      once = true;
    }
  }
  @Override
  public boolean onTouchEvent(MotionEvent ev) {
    int action = ev.getAction();
    switch (action){
      // Up时,进行判断,如果显示区域大于菜单宽度一半则完全显示,否则隐藏
      case MotionEvent.ACTION_UP:{
        int scrollX = getScrollX();
        if(scrollX > mHalfMenuWidth){
          this.smoothScrollTo(mMenuWidth,0);
          isOpen = false;
        }
        else{
          this.smoothScrollTo(0,0);
          isOpen = true;
        }
        return true;
      }
    }
    return super.onTouchEvent(ev);
  }
  /**
   * 打开菜单
   */
  public void openMenu()
  {
    if (isOpen)
      return;
    this.smoothScrollTo(0, 0);
    isOpen = true;
  }
  /**
   * 关闭菜单
   */
  public void closeMenu()
  {
    if (isOpen)
    {
      this.smoothScrollTo(mMenuWidth, 0);
      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(mMenu, leftScale);
    ViewHelper.setScaleY(mMenu, leftScale);
    ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * (1 - scale));
    ViewHelper.setTranslationX(mMenu, mMenuWidth * scale * 0.7f);
    ViewHelper.setPivotX(mContent, 0);
    ViewHelper.setPivotY(mContent, mContent.getHeight() / 2);
    ViewHelper.setScaleX(mContent, rightScale);
    ViewHelper.setScaleY(mContent, rightScale);
  }
}

布局文件和资源文件(xml)



  
    
      
      
        

你可能感兴趣的:(基于Android实现仿QQ5.0侧滑)