/* * Copyright (C) 2012 Capricorn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.forfan.bigbang.view; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationSet; import android.view.animation.DecelerateInterpolator; import android.view.animation.RotateAnimation; import android.view.animation.ScaleAnimation; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; import com.forfan.bigbang.R; import com.forfan.bigbang.util.ConstantUtil; import com.forfan.bigbang.util.ViewUtil; import com.shang.commonjar.contentProvider.SPHelper; /** * A custom view that looks like the menu in <a href="https://path.com">Path * 2.0</a> (for iOS). * * @author Capricorn * */ public class ArcMenu extends FrameLayout { private ArcLayout mArcLayout; private ImageView mHintView; private ViewGroup controlLayout; private OnModeSeletedListener mOnModeSeleter; private int mPosition; public ArcMenu(Context context) { super(context); init(context); } public ArcMenu(Context context, AttributeSet attrs) { super(context, attrs); init(context); applyAttrs(attrs); } private void init(Context context) { LayoutInflater li = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); li.inflate(R.layout.arc_menu, this); mArcLayout = (ArcLayout) findViewById(R.id.item_layout); controlLayout = (ViewGroup) findViewById(R.id.control_layout); controlLayout.setClickable(true); controlLayout.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { mHintView.startAnimation(createHintSwitchAnimation(mArcLayout.isExpanded())); mArcLayout.switchState(true,mPosition); mArcLayout.postDelayed(new Runnable() { @Override public void run() { if(mOnModeSeleter != null) mOnModeSeleter.onModeSelected(); } },350); } return false; } }); mHintView = (ImageView) findViewById(R.id.control_hint); } private void applyAttrs(AttributeSet attrs) { if (attrs != null) { TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ArcLayout, 0, 0); float fromDegrees = a.getFloat(R.styleable.ArcLayout_fromDegrees, ArcLayout.DEFAULT_FROM_DEGREES); float toDegrees = a.getFloat(R.styleable.ArcLayout_toDegrees, ArcLayout.DEFAULT_TO_DEGREES); mArcLayout.setArc(fromDegrees, toDegrees); int defaultChildSize = mArcLayout.getChildSize(); int newChildSize = a.getDimensionPixelSize(R.styleable.ArcLayout_childSize, defaultChildSize); mArcLayout.setChildSize(newChildSize); a.recycle(); } } public void applySizeChange(float persents){ setArcLayoutSize((int) (ViewUtil.dp2px(146)* persents)); setMenuSize((int) (ViewUtil.dp2px(40)* persents)); setHintViewSize((int) (ViewUtil.dp2px(47)* persents)); int padding = (int) (ViewUtil.dp2px(10)*persents); mHintView.setPadding(padding,padding,padding,padding); mArcLayout.setMinRadius(persents); } public void setMenuSize(int radiu){ mArcLayout.setChildSize(radiu); } public void setHintViewSize(int width){ FrameLayout.LayoutParams layoutParams= (LayoutParams) mHintView.getLayoutParams(); if (layoutParams!=null){ layoutParams.width=width; layoutParams.height=width; mHintView.setLayoutParams(layoutParams); mHintView.setMaxWidth(width); mHintView.setMaxHeight(width); } } public void setArcLayoutSize(int width){ ViewGroup.LayoutParams layoutParams= (LayoutParams) mArcLayout.getLayoutParams(); if (layoutParams!=null){ layoutParams.width=width; layoutParams.height=width; mArcLayout.setLayoutParams(layoutParams); } } public void addItem(View item, OnClickListener listener) { mArcLayout.addView(item); item.setOnClickListener(getItemClickListener(listener)); } private OnClickListener getItemClickListener(final OnClickListener listener) { return new OnClickListener() { @Override public void onClick(final View viewClicked) { Animation animation = bindItemAnimation(viewClicked, true, 350); animation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { postDelayed(new Runnable() { @Override public void run() { itemDidDisappear(); } }, 0); } }); final int itemCount = mArcLayout.getChildCount(); for (int i = 0; i < itemCount; i++) { View item = mArcLayout.getChildAt(i); if (viewClicked != item) { bindItemAnimation(item, false, 300); } } mArcLayout.invalidate(); mHintView.startAnimation(createHintSwitchAnimation(true)); if (listener != null) { listener.onClick(viewClicked); } } }; } private Animation bindItemAnimation(final View child, final boolean isClicked, final long duration) { Animation animation = createItemDisapperAnimation(duration, isClicked); child.setAnimation(animation); return animation; } private void itemDidDisappear() { final int itemCount = mArcLayout.getChildCount(); for (int i = 0; i < itemCount; i++) { View item = mArcLayout.getChildAt(i); item.clearAnimation(); } mArcLayout.switchState(false,mPosition); } private static Animation createItemDisapperAnimation(final long duration, final boolean isClicked) { AnimationSet animationSet = new AnimationSet(true); animationSet.addAnimation(new ScaleAnimation(1.0f, isClicked ? 2.0f : 0.0f, 1.0f, isClicked ? 2.0f : 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f)); animationSet.addAnimation(new AlphaAnimation(1.0f, 0.0f)); animationSet.setDuration(duration); animationSet.setInterpolator(new DecelerateInterpolator()); animationSet.setFillAfter(true); return animationSet; } private static Animation createHintSwitchAnimation(final boolean expanded) { Animation animation = new RotateAnimation(expanded ? 45 : 0, expanded ? 0 : 45, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); animation.setStartOffset(0); animation.setDuration(100); animation.setInterpolator(new DecelerateInterpolator()); animation.setFillAfter(true); return animation; } public void performClickShowMenu(int position) { mPosition = position; mHintView.startAnimation(createHintSwitchAnimation(mArcLayout.isExpanded())); mArcLayout.switchState(true,position); } /** * 根据按钮位置改变子菜单方向 */ public void refreshPathMenu(int position) { FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mArcLayout.getLayoutParams(); FrameLayout.LayoutParams params1 = (FrameLayout.LayoutParams) controlLayout.getLayoutParams(); switch (position) { case PathMenu.LEFT_TOP://左上 params1.gravity = Gravity.LEFT | Gravity.TOP; params.gravity = Gravity.LEFT | Gravity.TOP; mArcLayout.setArc(0, 90, position); break; case PathMenu.LEFT_CENTER://左中 params1.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL; params.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL; mArcLayout.setArc(270, 270 + 180, position); break; case PathMenu.LEFT_BOTTOM://左下 params1.gravity = Gravity.LEFT | Gravity.BOTTOM; params.gravity = Gravity.LEFT | Gravity.BOTTOM; mArcLayout.setArc(270, 360, position); break; case PathMenu.RIGHT_TOP://右上 params1.gravity = Gravity.RIGHT | Gravity.TOP; params.gravity = Gravity.RIGHT | Gravity.TOP; mArcLayout.setArc(90, 180, position); break; case PathMenu.RIGHT_CENTER://右中 params1.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL; params.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL; mArcLayout.setArc(90, 270, position); break; case PathMenu.RIGHT_BOTTOM://右下 params1.gravity = Gravity.BOTTOM | Gravity.RIGHT; params.gravity = Gravity.BOTTOM | Gravity.RIGHT; mArcLayout.setArc(180, 270, position); break; case PathMenu.CENTER_TOP://上中 params1.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; params.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; mArcLayout.setArc(0, 180, position); break; case PathMenu.CENTER_BOTTOM://下中 params1.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; mArcLayout.setArc(180, 360, position); break; case PathMenu.CENTER: params1.gravity = Gravity.CENTER; params.gravity = Gravity.CENTER; mArcLayout.setArc(0, 360, position); break; } controlLayout.setLayoutParams(params1); mArcLayout.setLayoutParams(params); } public void reset() { mHintView.startAnimation(createHintSwitchAnimation(mArcLayout.isExpanded())); if (mArcLayout.isExpanded()) { mArcLayout.switchState(false); } mArcLayout.setExpand(false); } public void removeAllItemViews() { mArcLayout.removeAllViews(); } public ImageView getHintView() { return mHintView; } public interface OnModeSeletedListener{ void onModeSelected(); void onNothing(); } public void setOnModeSeletedListener(OnModeSeletedListener onModeSeletedListener) { mOnModeSeleter = onModeSeletedListener; } }