Android satellite menu Animation.
—> AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0" package="android.view.satellitemenu"> <uses-sdk android:minSdkVersion="7"/> <application android:debuggable="false" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.Light"> <activity android:label="@string/app_name" android:name=".SatelliteMenuActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest>
In values Folder
sat_attrs.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="SatelliteMenu"> <attr name="expandDuration" format="integer" /> <attr name="closeOnClick" format="boolean" /> <attr name="totalSpacingDegree" format="float" /> <attr name="satelliteDistance" format="dimension" /> <attr name="mainImage" format="reference" /> </declare-styleable> </resources>
In Layout Folder
sat_main.xml
<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" > <ImageView android:id="@+id/sat_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|left" android:src="@drawable/sat_main" /> </merge>
sat_item_cr.xml
<?xml version="1.0" encoding="utf-8"?> <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/sat_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/sat_item" android:visibility="gone" android:layout_gravity="bottom|left" />
main.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:sat="http://schemas.android.com/apk/res/android.view.satellitemenu" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <android.view.satellitemenu.SatelliteMenu android:id="@+id/menu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|left" android:layout_margin="8dp" sat:satelliteDistance="170dp" sat:mainImage="@drawable/ic_launcher" sat:totalSpacingDegree="90" sat:closeOnClick="true" sat:expandDuration="500"/> </FrameLayout>
res/anim
sat_item_anim_click.xml
<?xml version="1.0" encoding="utf-8"?> <!-- android:interpolator="@android:anim/bounce_interpolator" --> <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="true" android:fillAfter="false" android:fillEnabled="false"> <scale android:fromXScale="1" android:toXScale="3" android:fromYScale="1" android:toYScale="3" android:pivotX="50%" android:pivotY="50%" android:duration="400"/> <alpha android:fromAlpha="1" android:toAlpha="0" android:duration="150" android:startOffset="250"/> </set>
sat_item_anticipate_interpolator.xml
<?xml version="1.0" encoding="utf-8"?> <anticipateInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:tension="3.0"/>
sat_item_click_interpolator.xml
<?xml version="1.0" encoding="utf-8"?> <decelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:factor="1.2"/>
sat_item_in_rotate_interpolator.xml
<?xml version="1.0" encoding="utf-8"?> <accelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:factor="1.2"/>
sat_item_out_rotate_interpolator.xml
<?xml version="1.0" encoding="utf-8"?> <decelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:factor="1.0"/>
sat_item_overshoot_interpolator.xml
<?xml version="1.0" encoding="utf-8"?> <overshootInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:tension="3.0"/>
sat_main_rotate_left.xml
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator" android:fromDegrees="0" android:toDegrees="-135" android:pivotX="50%" android:pivotY="50%" android:duration="300" android:fillAfter="true" android:fillEnabled="true"/>
sat_main_rotate_right.xml
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator" android:fromDegrees="-135" android:toDegrees="0" android:pivotX="50%" android:pivotY="50%" android:duration="300" android:fillAfter="true" android:fillEnabled="true"/>
ArrayDegreeProvider.java
package android.view.satellitemenu; public class ArrayDegreeProvider implements IDegreeProvider { private float[] degrees; public ArrayDegreeProvider(float[] degrees) { this.degrees = degrees; } public float[] getDegrees(int count, float totalDegrees){ if(degrees == null || degrees.length != count){ throw new IllegalArgumentException("Provided delta degrees and the action count are not the same."); } return degrees; } }
DefaultDegreeProvider.java
package android.view.satellitemenu; public class DefaultDegreeProvider implements IDegreeProvider { public float[] getDegrees(int count, float totalDegrees){ if(count < 1) { return new float[]{}; } float[] result = null; int tmpCount = 0; if(count < 4){ tmpCount = count+1; }else{ tmpCount = count-1; } result = new float[count]; float delta = totalDegrees / tmpCount; for(int index=0; index<count; index++){ int tmpIndex = index; if(count < 4){ tmpIndex = tmpIndex+1; } result[index] = tmpIndex * delta; } return result; } }
IDegreeProvider.java
package android.view.satellitemenu; public interface IDegreeProvider { public float[] getDegrees(int count, float totalDegrees); }
LinearDegreeProvider.java
package android.view.satellitemenu; public class LinearDegreeProvider implements IDegreeProvider { public float[] getDegrees(int count, float totalDegrees){ if(count < 1){ return new float[]{}; } if(count == 1){ return new float[]{45}; } float[] result = null; int tmpCount = count-1; result = new float[count]; float delta = totalDegrees / tmpCount; for(int index=0; index<count; index++){ int tmpIndex = index; result[index] = tmpIndex * delta; } return result; } }
SatelliteAnimationCreator.java
package android.view.satellitemenu; import android.content.Context; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; import android.view.animation.RotateAnimation; import android.view.animation.TranslateAnimation; import android.view.satellitemenu.R; public class SatelliteAnimationCreator { public static Animation createItemInAnimation(Context context, int index, long expandDuration, int x, int y){ RotateAnimation rotate = new RotateAnimation(720, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotate.setInterpolator(context, R.anim.sat_item_in_rotate_interpolator); rotate.setDuration(expandDuration); TranslateAnimation translate = new TranslateAnimation(x, 0, y, 0); long delay = 250; if(expandDuration <= 250){ delay = expandDuration / 3; } long duration = 400; if((expandDuration-delay) > duration){ duration = expandDuration-delay; } translate.setDuration(duration); translate.setStartOffset(delay); translate.setInterpolator(context, R.anim.sat_item_anticipate_interpolator); AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0f); long alphaDuration = 10; if(expandDuration < 10){ alphaDuration = expandDuration / 10; } alphaAnimation.setDuration(alphaDuration); alphaAnimation.setStartOffset((delay + duration) - alphaDuration); AnimationSet animationSet = new AnimationSet(false); animationSet.setFillAfter(false); animationSet.setFillBefore(true); animationSet.setFillEnabled(true); animationSet.addAnimation(alphaAnimation); animationSet.addAnimation(rotate); animationSet.addAnimation(translate); animationSet.setStartOffset(30*index); animationSet.start(); animationSet.startNow(); return animationSet; } public static Animation createItemOutAnimation(Context context, int index, long expandDuration, int x, int y){ AlphaAnimation alphaAnimation = new AlphaAnimation(0f, 1f); long alphaDuration = 60; if(expandDuration < 60){ alphaDuration = expandDuration / 4; } alphaAnimation.setDuration(alphaDuration); alphaAnimation.setStartOffset(0); TranslateAnimation translate = new TranslateAnimation(0, x, 0, y); translate.setStartOffset(0); translate.setDuration(expandDuration); translate.setInterpolator(context, R.anim.sat_item_overshoot_interpolator); RotateAnimation rotate = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotate.setInterpolator(context, R.anim.sat_item_out_rotate_interpolator); long duration = 100; if(expandDuration <= 150){ duration = expandDuration / 3; } rotate.setDuration(expandDuration-duration); rotate.setStartOffset(duration); AnimationSet animationSet = new AnimationSet(false); animationSet.setFillAfter(false); animationSet.setFillBefore(true); animationSet.setFillEnabled(true); //animationSet.addAnimation(alphaAnimation); //animationSet.addAnimation(rotate); animationSet.addAnimation(translate); animationSet.setStartOffset(30*index); return animationSet; } public static Animation createMainButtonAnimation(Context context){ return AnimationUtils.loadAnimation(context, R.anim.sat_main_rotate_left); } public static Animation createMainButtonInverseAnimation(Context context){ return AnimationUtils.loadAnimation(context, R.anim.sat_main_rotate_right); } public static Animation createItemClickAnimation(Context context){ return AnimationUtils.loadAnimation(context, R.anim.sat_item_anim_click); } public static int getTranslateX(float degree, int distance){ return Double.valueOf(distance * Math.cos(Math.toRadians(degree))).intValue(); } public static int getTranslateY(float degree, int distance){ return Double.valueOf(-1 * distance * Math.sin(Math.toRadians(degree))).intValue(); } }
SatelliteMenu.java
package android.view.satellitemenu; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.animation.Animation; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; public class SatelliteMenu extends FrameLayout { private static final int DEFAULT_SATELLITE_DISTANCE = 200; private static final float DEFAULT_TOTAL_SPACING_DEGREES = 90f; private static final boolean DEFAULT_CLOSE_ON_CLICK = true; private static final int DEFAULT_EXPAND_DURATION = 400; private Animation mainRotateRight; private Animation mainRotateLeft; private ImageView imgMain; private SateliteClickedListener itemClickedListener; private InternalSatelliteOnClickListener internalItemClickListener; private List<SatelliteMenuItem> menuItems = new ArrayList<SatelliteMenuItem>(); private Map<View, SatelliteMenuItem> viewToItemMap = new HashMap<View, SatelliteMenuItem>(); private AtomicBoolean plusAnimationActive = new AtomicBoolean(false); // ?? how to save/restore? private IDegreeProvider gapDegreesProvider = new DefaultDegreeProvider(); //States of these variables are saved private boolean rotated = false; private int measureDiff = 0; //States of these variables are saved - Also configured from XML private float totalSpacingDegree = DEFAULT_TOTAL_SPACING_DEGREES; private int satelliteDistance = DEFAULT_SATELLITE_DISTANCE; private int expandDuration = DEFAULT_EXPAND_DURATION; private boolean closeItemsOnClick = DEFAULT_CLOSE_ON_CLICK; public SatelliteMenu(Context context) { super(context); init(context, null, 0); } public SatelliteMenu(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0); } public SatelliteMenu(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } private void init(Context context, AttributeSet attrs, int defStyle) { LayoutInflater.from(context).inflate(R.layout.sat_main, this, true); imgMain = (ImageView) findViewById(R.id.sat_main); if(attrs != null){ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SatelliteMenu, defStyle, 0); satelliteDistance = typedArray.getDimensionPixelSize(R.styleable.SatelliteMenu_satelliteDistance, DEFAULT_SATELLITE_DISTANCE); totalSpacingDegree = typedArray.getFloat(R.styleable.SatelliteMenu_totalSpacingDegree, DEFAULT_TOTAL_SPACING_DEGREES); closeItemsOnClick = typedArray.getBoolean(R.styleable.SatelliteMenu_closeOnClick, DEFAULT_CLOSE_ON_CLICK); expandDuration = typedArray.getInt(R.styleable.SatelliteMenu_expandDuration, DEFAULT_EXPAND_DURATION); //float satelliteDistance = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 170, getResources().getDisplayMetrics()); typedArray.recycle(); } mainRotateLeft = SatelliteAnimationCreator.createMainButtonAnimation(context); mainRotateRight = SatelliteAnimationCreator.createMainButtonInverseAnimation(context); Animation.AnimationListener plusAnimationListener = new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { plusAnimationActive.set(false); } }; mainRotateLeft.setAnimationListener(plusAnimationListener); mainRotateRight.setAnimationListener(plusAnimationListener); imgMain.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SatelliteMenu.this.onClick(); } }); internalItemClickListener = new InternalSatelliteOnClickListener(this); } private void onClick() { if (plusAnimationActive.compareAndSet(false, true)) { if (!rotated) { imgMain.startAnimation(mainRotateLeft); for (SatelliteMenuItem item : menuItems) { item.getView().startAnimation(item.getOutAnimation()); } } else { imgMain.startAnimation(mainRotateRight); for (SatelliteMenuItem item : menuItems) { item.getView().startAnimation(item.getInAnimation()); } } rotated = !rotated; } } private void openItems() { if (plusAnimationActive.compareAndSet(false, true)) { if (!rotated) { imgMain.startAnimation(mainRotateLeft); for (SatelliteMenuItem item : menuItems) { item.getView().startAnimation(item.getOutAnimation()); } } rotated = !rotated; } } private void closeItems() { if (plusAnimationActive.compareAndSet(false, true)) { if (rotated) { imgMain.startAnimation(mainRotateRight); for (SatelliteMenuItem item : menuItems) { item.getView().startAnimation(item.getInAnimation()); } } rotated = !rotated; } } public void addItems(List<SatelliteMenuItem> items) { menuItems.addAll(items); this.removeView(imgMain); TextView tmpView = new TextView(getContext()); tmpView.setLayoutParams(new FrameLayout.LayoutParams(0, 0)); float[] degrees = getDegrees(menuItems.size()); int index = 0; for (SatelliteMenuItem menuItem : menuItems) { int finalX = SatelliteAnimationCreator.getTranslateX( degrees[index], satelliteDistance); int finalY = SatelliteAnimationCreator.getTranslateY( degrees[index], satelliteDistance); ImageView itemView = (ImageView) LayoutInflater.from(getContext()) .inflate(R.layout.sat_item_cr, this, false); ImageView cloneView = (ImageView) LayoutInflater.from(getContext()) .inflate(R.layout.sat_item_cr, this, false); itemView.setTag(menuItem.getId()); cloneView.setVisibility(View.GONE); itemView.setVisibility(View.GONE); cloneView.setOnClickListener(internalItemClickListener); cloneView.setTag(Integer.valueOf(menuItem.getId())); FrameLayout.LayoutParams layoutParams = getLayoutParams(cloneView); layoutParams.bottomMargin = Math.abs(finalY); layoutParams.leftMargin = Math.abs(finalX); cloneView.setLayoutParams(layoutParams); if (menuItem.getImgResourceId() > 0) { itemView.setImageResource(menuItem.getImgResourceId()); cloneView.setImageResource(menuItem.getImgResourceId()); } else if (menuItem.getImgDrawable() != null) { itemView.setImageDrawable(menuItem.getImgDrawable()); cloneView.setImageDrawable(menuItem.getImgDrawable()); } Animation itemOut = SatelliteAnimationCreator.createItemOutAnimation(getContext(), index,expandDuration, finalX, finalY); Animation itemIn = SatelliteAnimationCreator.createItemInAnimation(getContext(), index, expandDuration, finalX, finalY); Animation itemClick = SatelliteAnimationCreator.createItemClickAnimation(getContext()); menuItem.setView(itemView); menuItem.setCloneView(cloneView); menuItem.setInAnimation(itemIn); menuItem.setOutAnimation(itemOut); menuItem.setClickAnimation(itemClick); menuItem.setFinalX(finalX); menuItem.setFinalY(finalY); itemIn.setAnimationListener(new SatelliteAnimationListener(itemView, true, viewToItemMap)); itemOut.setAnimationListener(new SatelliteAnimationListener(itemView, false, viewToItemMap)); itemClick.setAnimationListener(new SatelliteItemClickAnimationListener(this, menuItem.getId())); this.addView(itemView); this.addView(cloneView); viewToItemMap.put(itemView, menuItem); viewToItemMap.put(cloneView, menuItem); index++; } this.addView(imgMain); } private float[] getDegrees(int count) { return gapDegreesProvider.getDegrees(count, totalSpacingDegree); } private void recalculateMeasureDiff() { int itemWidth = 0; if (menuItems.size() > 0) { itemWidth = menuItems.get(0).getView().getWidth(); } measureDiff = Float.valueOf(satelliteDistance * 0.2f).intValue() + itemWidth; } private void resetItems() { if (menuItems.size() > 0) { List<SatelliteMenuItem> items = new ArrayList<SatelliteMenuItem>( menuItems); menuItems.clear(); this.removeAllViews(); addItems(items); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); recalculateMeasureDiff(); int totalHeight = imgMain.getHeight() + satelliteDistance + measureDiff; int totalWidth = imgMain.getWidth() + satelliteDistance + measureDiff; setMeasuredDimension(totalWidth, totalHeight); } private static class SatelliteItemClickAnimationListener implements Animation.AnimationListener { private WeakReference<SatelliteMenu> menuRef; private int tag; public SatelliteItemClickAnimationListener(SatelliteMenu menu, int tag) { this.menuRef = new WeakReference<SatelliteMenu>(menu); this.tag = tag; } @Override public void onAnimationEnd(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { SatelliteMenu menu = menuRef.get(); if(menu != null && menu.closeItemsOnClick){ menu.close(); if(menu.itemClickedListener != null){ menu.itemClickedListener.eventOccured(tag); } } } } private static class SatelliteAnimationListener implements Animation.AnimationListener { private WeakReference<View> viewRef; private boolean isInAnimation; private Map<View, SatelliteMenuItem> viewToItemMap; public SatelliteAnimationListener(View view, boolean isIn, Map<View, SatelliteMenuItem> viewToItemMap) { this.viewRef = new WeakReference<View>(view); this.isInAnimation = isIn; this.viewToItemMap = viewToItemMap; } @Override public void onAnimationStart(Animation animation) { if (viewRef != null) { View view = viewRef.get(); if (view != null) { SatelliteMenuItem menuItem = viewToItemMap.get(view); if (isInAnimation) { menuItem.getView().setVisibility(View.VISIBLE); menuItem.getCloneView().setVisibility(View.GONE); } else { menuItem.getCloneView().setVisibility(View.GONE); menuItem.getView().setVisibility(View.VISIBLE); } } } } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if (viewRef != null) { View view = viewRef.get(); if (view != null) { SatelliteMenuItem menuItem = viewToItemMap.get(view); if (isInAnimation) { menuItem.getView().setVisibility(View.GONE); menuItem.getCloneView().setVisibility(View.GONE); } else { menuItem.getCloneView().setVisibility(View.VISIBLE); menuItem.getView().setVisibility(View.GONE); } } } } } public Map<View, SatelliteMenuItem> getViewToItemMap() { return viewToItemMap; } private static FrameLayout.LayoutParams getLayoutParams(View view) { return (FrameLayout.LayoutParams) view.getLayoutParams(); } private static class InternalSatelliteOnClickListener implements View.OnClickListener { private WeakReference<SatelliteMenu> menuRef; public InternalSatelliteOnClickListener(SatelliteMenu menu) { this.menuRef = new WeakReference<SatelliteMenu>(menu); } @Override public void onClick(View v) { SatelliteMenu menu = menuRef.get(); if(menu != null){ SatelliteMenuItem menuItem = menu.getViewToItemMap().get(v); v.startAnimation(menuItem.getClickAnimation()); } } } /** * Sets the click listener for satellite items. * * @param itemClickedListener */ public void setOnItemClickedListener(SateliteClickedListener itemClickedListener) { this.itemClickedListener = itemClickedListener; } /** * Defines the algorithm to define the gap between each item. * Note: Calling before adding items is strongly recommended. * * @param gapDegreeProvider */ public void setGapDegreeProvider(IDegreeProvider gapDegreeProvider) { this.gapDegreesProvider = gapDegreeProvider; resetItems(); } /** * Defines the total space between the initial and final item in degrees. * Note: Calling before adding items is strongly recommended. * * @param totalSpacingDegree The degree between initial and final items. */ public void setTotalSpacingDegree(float totalSpacingDegree) { this.totalSpacingDegree = totalSpacingDegree; resetItems(); } /** * Sets the distance of items from the center in pixels. * Note: Calling before adding items is strongly recommended. * * @param distance the distance of items to center in pixels. */ public void setSatelliteDistance(int distance) { this.satelliteDistance = distance; resetItems(); } /** * Sets the duration for expanding and collapsing the items in miliseconds. * Note: Calling before adding items is strongly recommended. * * @param expandDuration the duration for expanding and collapsing the items in miliseconds. */ public void setExpandDuration(int expandDuration) { this.expandDuration = expandDuration; resetItems(); } /** * Sets the image resource for the center button. * * @param resource The image resource. */ public void setMainImage(int resource) { this.imgMain.setImageResource(resource); } /** * Sets the image drawable for the center button. * * @param resource The image drawable. */ public void setMainImage(Drawable drawable) { this.imgMain.setImageDrawable(drawable); } /** * Defines if the menu shall collapse the items when an item is clicked. Default value is true. * * @param closeItemsOnClick */ public void setCloseItemsOnClick(boolean closeItemsOnClick) { this.closeItemsOnClick = closeItemsOnClick; } /** * The listener class for item click event. * @author Siyamed SINIR */ public interface SateliteClickedListener { /** * When an item is clicked, informs with the id of the item, which is given while adding the items. * * @param id The id of the item. */ public void eventOccured(int id); } /** * Expand the menu items. */ public void expand() { openItems(); } /** * Collapse the menu items */ public void close() { closeItems(); } @Override protected Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.rotated = rotated; ss.totalSpacingDegree = totalSpacingDegree; ss.satelliteDistance = satelliteDistance; ss.measureDiff = measureDiff; ss.expandDuration = expandDuration; ss.closeItemsOnClick = closeItemsOnClick; return ss; } @Override protected void onRestoreInstanceState(Parcelable state) { SavedState ss = (SavedState) state; rotated = ss.rotated; totalSpacingDegree = ss.totalSpacingDegree; satelliteDistance = ss.satelliteDistance; measureDiff = ss.measureDiff; expandDuration = ss.expandDuration; closeItemsOnClick = ss.closeItemsOnClick; super.onRestoreInstanceState(ss.getSuperState()); } static class SavedState extends BaseSavedState { boolean rotated; private float totalSpacingDegree; private int satelliteDistance; private int measureDiff; private int expandDuration; private boolean closeItemsOnClick; SavedState(Parcelable superState) { super(superState); } public SavedState(Parcel in) { super(in); rotated = Boolean.valueOf(in.readString()); totalSpacingDegree = in.readFloat(); satelliteDistance = in.readInt(); measureDiff = in.readInt(); expandDuration = in.readInt(); closeItemsOnClick = Boolean.valueOf(in.readString()); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { out.writeString(Boolean.toString(rotated)); out.writeFloat(totalSpacingDegree); out.writeInt(satelliteDistance); out.writeInt(measureDiff); out.writeInt(expandDuration); out.writeString(Boolean.toString(closeItemsOnClick)); } public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } }
SatelliteMenuActivity.java
package android.view.satellitemenu; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.satellitemenu.SatelliteMenu.SateliteClickedListener; public class SatelliteMenuActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); SatelliteMenu menu = (SatelliteMenu) findViewById(R.id.menu); List<SatelliteMenuItem> items = new ArrayList<SatelliteMenuItem>(); items.add(new SatelliteMenuItem(4, R.drawable.ic_1)); items.add(new SatelliteMenuItem(4, R.drawable.ic_3)); items.add(new SatelliteMenuItem(4, R.drawable.ic_4)); items.add(new SatelliteMenuItem(3, R.drawable.ic_5)); items.add(new SatelliteMenuItem(2, R.drawable.ic_6)); items.add(new SatelliteMenuItem(1, R.drawable.ic_2)); menu.addItems(items); menu.setOnItemClickedListener(new SateliteClickedListener() { public void eventOccured(int id) { Log.i("sat", "Clicked on " + id); } }); } }
SatelliteMenuItem.java
package android.view.satellitemenu; import android.graphics.drawable.Drawable; import android.view.animation.Animation; import android.widget.ImageView; public class SatelliteMenuItem { private int id; private int imgResourceId; private Drawable imgDrawable; private ImageView view; private ImageView cloneView; private Animation outAnimation; private Animation inAnimation; private Animation clickAnimation; private int finalX; private int finalY; public SatelliteMenuItem(int id, int imgResourceId) { this.imgResourceId = imgResourceId; this.id = id; } public SatelliteMenuItem(int id, Drawable imgDrawable) { this.imgDrawable = imgDrawable; this.id = id; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getImgResourceId() { return imgResourceId; } public void setImgResourceId(int imgResourceId) { this.imgResourceId = imgResourceId; } public Drawable getImgDrawable() { return imgDrawable; } public void setImgDrawable(Drawable imgDrawable) { this.imgDrawable = imgDrawable; } void setView(ImageView view) { this.view = view; } ImageView getView() { return view; } void setInAnimation(Animation inAnimation) { this.inAnimation = inAnimation; } Animation getInAnimation() { return inAnimation; } void setOutAnimation(Animation outAnimation) { this.outAnimation = outAnimation; } Animation getOutAnimation() { return outAnimation; } void setFinalX(int finalX) { this.finalX = finalX; } void setFinalY(int finalY) { this.finalY = finalY; } int getFinalX() { return finalX; } int getFinalY() { return finalY; } void setCloneView(ImageView cloneView) { this.cloneView = cloneView; } ImageView getCloneView() { return cloneView; } void setClickAnimation(Animation clickAnim) { this.clickAnimation = clickAnim; } Animation getClickAnimation() { return clickAnimation; } }
Leave a Reply