package org.kymjs.music.ui.widget; import java.util.ArrayList; import java.util.List; import org.kymjs.kjframe.utils.KJLoger; import org.kymjs.music.R; import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.app.Activity; import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; import android.util.DisplayMetrics; import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.AnimationUtils; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ScrollView; import com.nineoldandroids.view.ViewHelper; /** * @User: special Date: 13-12-10 * @Time: 下午10:44 * @Mail: specialcyci@gmail.com * @kymjs: 本类是对菜单界面设置动画与样式 */ public class ResideMenu extends FrameLayout implements GestureDetector.OnGestureListener { private ImageView iv_shadow; private ImageView iv_background; private LinearLayout layout_menu; private ScrollView sv_menu; private AnimatorSet scaleUp_shadow; private AnimatorSet scaleUp_activity; private AnimatorSet scaleDown_activity; private AnimatorSet scaleDown_shadow; /** 这个activity是该控件依附的activity */ private Activity activity; /** 这个布局来自activity */ private ViewGroup view_decor; /** 这个ViewGroup来自activity */ private ViewGroup view_activity; /** 标志菜单打开状态 */ private boolean isOpened; private GestureDetector gestureDetector; private float shadow_ScaleX; /** 不想拦截哪个View的触摸屏事件 */ private List<View> ignoredViews; private List<ResideMenuItem> menuItems; private final DisplayMetrics displayMetrics = new DisplayMetrics(); private OnMenuListener menuListener; public ResideMenu(Context context) { super(context); initViews(context); } private void initViews(Context context) { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); inflater.inflate(R.layout.residemenu, this); sv_menu = (ScrollView) findViewById(R.id.sv_menu); iv_shadow = (ImageView) findViewById(R.id.iv_shadow); layout_menu = (LinearLayout) findViewById(R.id.layout_menu); iv_background = (ImageView) findViewById(R.id.iv_background); } /** * 这个方法用来设置菜单项需要显示到哪一个activity * * @param activity */ public void attachToActivity(Activity activity) { initValue(activity); setShadowScaleXByOrientation(); buildAnimationSet(); } private void initValue(Activity activity) { this.activity = activity; menuItems = new ArrayList<ResideMenuItem>(); gestureDetector = new GestureDetector(activity, this); ignoredViews = new ArrayList<View>(); view_decor = (ViewGroup) activity.getWindow().getDecorView(); view_activity = (ViewGroup) view_decor.getChildAt(0); } private void setShadowScaleXByOrientation() { int orientation = getResources().getConfiguration().orientation; if (orientation == Configuration.ORIENTATION_LANDSCAPE) { shadow_ScaleX = 0.5335f; } else if (orientation == Configuration.ORIENTATION_PORTRAIT) { shadow_ScaleX = 0.56f; } } /** * 设置背景图片 */ public void setBackground(int imageResrouce) { iv_background.setImageResource(imageResrouce); } /** * 在activity下面显示阴影 */ public void setShadowVisible(boolean isVisible) { if (isVisible) iv_shadow.setImageResource(R.drawable.shadow); else iv_shadow.setImageBitmap(null); } /** * 添加菜单项到菜单 */ public void addMenuItem(ResideMenuItem menuItem) { this.menuItems.add(menuItem); } /** * 用List设置菜单项 */ public void setMenuItems(List<ResideMenuItem> menuItems) { this.menuItems = menuItems; } /** * 得到菜单项集合 */ public List<ResideMenuItem> getMenuItems() { return menuItems; } /** * 如果你需要在activity关闭或打开时设置某事件,设置这个监听器 */ public void setMenuListener(OnMenuListener menuListener) { this.menuListener = menuListener; } /** * activity关闭或打开时的回调 */ public OnMenuListener getMenuListener() { return menuListener; } /** * 如果我们需要调用这个方法,要在在菜单显示之前,因为padding属性需要在onCreateView()之前设置 */ private void setViewPadding() { this.setPadding(view_activity.getPaddingLeft(), view_activity.getPaddingTop(), view_activity.getPaddingRight(), view_activity.getPaddingBottom()); } public void openMenu() { if (!isOpened) { isOpened = true; showOpenMenuRelative(); } } /** * 移除菜单布局(内容界面全屏时) */ private void removeMenuLayout() { ViewGroup parent = ((ViewGroup) sv_menu.getParent()); parent.removeView(sv_menu); } public void closeMenu() { if (isOpened) { isOpened = false; scaleUp_activity.start(); } } public boolean isOpened() { return isOpened; } /** * 打开菜单相关的方法 */ private void showOpenMenuRelative() { KJLoger.debug("========showOpenMenuRelative198====="); setViewPadding(); scaleDown_activity.start(); // remove self if has not remove if (getParent() != null) view_decor.removeView(this); if (sv_menu.getParent() != null) removeMenuLayout(); view_decor.addView(this, 0); view_decor.addView(sv_menu); } /** * 过渡动画 */ private final Animator.AnimatorListener animationListener = new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { if (isOpened) { layout_menu.removeAllViews(); showMenuDelay(); if (menuListener != null) menuListener.openMenu(); } } /** * 过渡动画结束时被回调 */ @Override public void onAnimationEnd(Animator animation) { // reset the view; if (!isOpened) { view_decor.removeView(ResideMenu.this); view_decor.removeView(sv_menu); if (menuListener != null) menuListener.closeMenu(); } } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }; /** * 延迟显示菜单(实现菜单逐个蹦出来的效果) */ private void showMenuDelay() { layout_menu.removeAllViews(); for (int i = 0; i < menuItems.size(); i++) showMenuItem(menuItems.get(i), i); } /** * 显示菜单 */ private void showMenuItem(ResideMenuItem menuItem, int menu_index) { layout_menu.addView(menuItem); ViewHelper.setAlpha(menuItem, 0); AnimatorSet scaleUp = new AnimatorSet(); scaleUp.playTogether( ObjectAnimator.ofFloat(menuItem, "translationX", -100.f, 0.0f), ObjectAnimator.ofFloat(menuItem, "alpha", 0.0f, 1.0f)); scaleUp.setInterpolator(AnimationUtils.loadInterpolator(activity, android.R.anim.anticipate_overshoot_interpolator)); // with animation; scaleUp.setStartDelay(50 * menu_index); scaleUp.setDuration(400).start(); } private void buildAnimationSet() { scaleUp_activity = buildScaleUpAnimation(view_activity, 1.0f, 1.0f); scaleUp_shadow = buildScaleUpAnimation(iv_shadow, 1.0f, 1.0f); scaleDown_activity = buildScaleDownAnimation(view_activity, 0.5f, 0.5f); scaleDown_shadow = buildScaleDownAnimation(iv_shadow, shadow_ScaleX, 0.59f); scaleUp_activity.addListener(animationListener); scaleUp_activity.playTogether(scaleUp_shadow); scaleDown_shadow.addListener(animationListener); scaleDown_activity.playTogether(scaleDown_shadow); } /** * 创建菜单退出的动画效果 * * @param target * @param targetScaleX * @param targetScaleY * @return */ private AnimatorSet buildScaleDownAnimation(View target, float targetScaleX, float targetScaleY) { KJLoger.debug("======buildScaleDownAnimation==298===="); int pivotX = (int) (getScreenWidth() * 1.5); int pivotY = (int) (getScreenHeight() * 0.5); ViewHelper.setPivotX(target, pivotX); ViewHelper.setPivotY(target, pivotY); AnimatorSet scaleDown = new AnimatorSet(); scaleDown.playTogether( ObjectAnimator.ofFloat(target, "scaleX", targetScaleX), ObjectAnimator.ofFloat(target, "scaleY", targetScaleY)); scaleDown.setInterpolator(AnimationUtils.loadInterpolator(activity, android.R.anim.decelerate_interpolator)); scaleDown.setDuration(250); return scaleDown; } /** * 创建菜单打开的动画效果 * * @param target * @param targetScaleX * @param targetScaleY * @return */ private AnimatorSet buildScaleUpAnimation(View target, float targetScaleX, float targetScaleY) { KJLoger.debug("=======buildScaleUpAnimation=============324"); AnimatorSet scaleUp = new AnimatorSet(); scaleUp.playTogether( ObjectAnimator.ofFloat(target, "scaleX", targetScaleX), ObjectAnimator.ofFloat(target, "scaleY", targetScaleY)); scaleUp.setDuration(250); return scaleUp; } /** * 添加不拦截触摸事件的控件 */ public void addIgnoredView(View v) { for (int i = 0; i < ignoredViews.size(); i++) { if (v == ignoredViews.get(i)) { return; } } ignoredViews.add(v); } /** * 移除不拦截触摸事件的控件 * * @param v */ public void removeIgnoredView(View v) { ignoredViews.remove(v); } /** * 清空不拦截触摸事件的控件 */ public void clearIgnoredViewList() { ignoredViews.clear(); } /** * 判断触摸是否发生在 不拦截触摸事件的控件上 * * @Rect类主要用于表示坐标系中的一块矩形区域 * @param ev * @return */ private boolean isInIgnoredView(MotionEvent ev) { Rect rect = new Rect(); for (View v : ignoredViews) { v.getGlobalVisibleRect(rect); // 将view位置保存到rect中 if (rect.contains((int) ev.getX(), (int) ev.getY())) return true; } return false; } // -------------------------------------------------------------------------- // // GestureListener // // -------------------------------------------------------------------------- @Override public boolean onTouchEvent(MotionEvent event) { return gestureDetector.onTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { gestureDetector.onTouchEvent(ev); return super.onInterceptTouchEvent(ev); } @Override public boolean onDown(MotionEvent motionEvent) { return false; } @Override public void onShowPress(MotionEvent motionEvent) { } @Override public boolean onSingleTapUp(MotionEvent motionEvent) { return false; } @Override public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent2, float v, float v2) { return false; } @Override public void onLongPress(MotionEvent motionEvent) { } @Override public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent2, float v, float v2) { if (isInIgnoredView(motionEvent) || isInIgnoredView(motionEvent2)) return false; int distanceX = (int) (motionEvent2.getX() - motionEvent.getX()); int distanceY = (int) (motionEvent2.getY() - motionEvent.getY()); int screenWidth = getScreenWidth(); if (Math.abs(distanceY) > screenWidth * 0.3) return false; if (Math.abs(distanceX) > screenWidth * 0.3) { if (distanceX > 0 && !isOpened) { // from left to right; openMenu(); } else if (distanceX < 0 && isOpened) { // from right th left; closeMenu(); } } return false; } public int getScreenHeight() { activity.getWindowManager().getDefaultDisplay() .getMetrics(displayMetrics); return displayMetrics.heightPixels; } public int getScreenWidth() { activity.getWindowManager().getDefaultDisplay() .getMetrics(displayMetrics); return displayMetrics.widthPixels; } public interface OnMenuListener { /** * 这个方法调用完成后将调用打开菜单的动画 */ public void openMenu(); /** * 这个方法调用完成后将调用关闭菜单的动画 */ public void closeMenu(); } }