假设做一个弹出的控件,我们能够进行加入view:
写class SatelliteMenu extends FrameLayout
private void init(Context context, AttributeSet attrs, int defStyle) { inflate(context, R.layout.sat_main, this); 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); }
<?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:src="@drawable/sat_main" android:layout_gravity="bottom|left" /> </merge> <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>
然后写加入Item的逻辑:
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);<strong>//这里是将cloneView置于itemview动画结束的位置</strong> 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 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); } } } } }
必须重写onMeature:
private void recalculateMeasureDiff() { int itemWidth = 0; if (menuItems.size() > 0) { itemWidth = menuItems.get(0).getView().getWidth(); } measureDiff = Float.valueOf(satelliteDistance * 0.2f).intValue() + itemWidth; } @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; System.out.println("====totalWidth="+totalWidth+"height="+totalHeight+"measureDiff="+measureDiff+"imgMain.getWidth()="+imgMain.getWidth()); setMeasuredDimension(totalWidth, totalHeight); }
save和恢复activity的状态:
@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]; } }; }