公司的手機OS升級,在最新的Camera擬用這樣的交互。感覺還不錯。 
 思路: 1.ViewGroup中包含imageView按鈕,根據顯示的個數動態計算布局,在onLayout中重新排布ImageView的位置。             2.重新排布ImageView的位置的時候使用動畫,動畫需要坐標即需要自定義ImageView添加位置屬性。             3.提供給外界方法用以決定顯示哪個按鈕,顯示幾個。
現在imageView已經有了mLastPosition mCurrentPosition 這個的位置屬性。
現在定義ViewGroup以動態添加刪除按鈕。新控件繼承LinearLayout方便實現
JPowerTranslateView extends LinearLayout然后在xml中添加控件及按鈕
<LinearLayout android:layout_width="match_parent" android:layout_height="56dp" android:orientation="horizontal" android:layout_alignParentTop="true"> <Button android:id="@+id/button1" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Button1"/> <Button android:id="@+id/button2" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Button2"/> </LinearLayout> <com.ws.jpower.animation.JPowerTranslateView android:id="@+id/animation_main_view" android:layout_width="match_parent" android:layout_height="56dp" android:background="#50ffffff" android:orientation="horizontal" android:layout_centerInParent="true"> <com.ws.jpower.animation.ItemView android:id="@+id/image_btn1" android:layout_width="80dp" android:layout_height="match_parent" android:scaleType="center" android:src="@drawable/ic_lava_Flash_auto_normal"/> <com.ws.jpower.animation.ItemView android:id="@+id/image_btn2" android:layout_width="80dp" android:layout_height="match_parent" android:src="@drawable/lava_hdr_auto_normal" android:scaleType="center"/> <com.ws.jpower.animation.ItemView android:id="@+id/image_btn3" android:layout_width="80dp" android:layout_height="match_parent" android:scaleType="center" android:src="@drawable/lava_shutter_type_gesture_5s_normal"/> <com.ws.jpower.animation.ItemView android:id="@+id/image_btn4" android:layout_width="80dp" android:layout_height="match_parent" android:scaleType="center" android:src="@drawable/lava_switch_camera_normal" android:visibility="gone"/> </com.ws.jpower.animation.JPowerTranslateView> </RelativeLayout>布局添加完后,在onFinishInflate方法中把GONE與VISIBLE的View分別放進不同的ArrayList
@Override protected void onFinishInflate() { super.onFinishInflate(); mGoneView = new ArrayList<ItemView>(); mVisibledView = new ArrayList<ItemView>(); mVisibleView = new ArrayList<ItemView>(); for (int i = 0; i < getChildCount(); i++) { if (getChildAt(i).getVisibility() == View.GONE) { mGoneView.add((ItemView) getChildAt(i)); } else { mVisibledView.add((ItemView) getChildAt(i)); mVisibleView.add((ItemView) getChildAt(i)); } } }然后根據需要顯示的View,從新排布
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mWidth = getMeasuredWidth(); if (mWidth == 0) { mWidth = mDisplayWith; } } //排布子View @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (mVisibleView != null && mVisibleView.size() > 0) { int visibleCount = mVisibleView.size();//需要顯示View的數量 itemWidth = mWidth / visibleCount; //等分父容器 for (int i = 0; i < visibleCount; i++) { int itemWh = 0; ItemView itemView = mVisibleView.get(i); itemWh = itemView.getWidth(); if (itemWh == 0) { itemWh = 80; } int maginLeft = itemWidth * i + (itemWidth - itemWh) / 2;//子View的left坐標,即把每個子View放置在每份的中間 itemView.layout(maginLeft, itemView.getTop(), maginLeft + itemWh, itemView.getBottom()); itemView.setmLastPosition(maginLeft);//保存位置信息,便于后期根據坐標做動畫 LastPosition } } }給外界提供一個方法,動態隱藏添加按鈕。 先回顧一下動畫demo
// 原始平移動畫TranslateAnimation private Animation getAnimation(float fromXValue, float toXValue, float fromYValue, float toYValue, long duration) { /*TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) float fromXDelta 動畫開始的點離當前View X坐標上的差值 float toXDelta 動畫結束的點離當前View X坐標上的差值 float fromYDelta 動畫開始的點離當前View Y坐標上的差值 float toYDelta 動畫開始的點離當前View Y坐標上的差值*/ TranslateAnimation animation = new TranslateAnimation(fromXValue, toXValue, fromYValue, toYValue); animation.setDuration(duration); animation.setInterpolator(new AccelerateInterpolator()); return animation; } // 屬性動畫PropertyValuesHolder public void propertyValuesHolder(View view, float fromXValue, float toXValue, float fromYValue, float toYValue, long duration) { PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("translationX", fromXValue, toXValue); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleY", fromYValue, toYValue); ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY); animator.setDuration(duration).start(); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { } }); } // 屬性動畫ObjectAnimator,AnimatorSet public void togetherAnimator(View view) { ObjectAnimator anim1 = ObjectAnimator.ofFloat(view, "alpha", 1.0f, 2f); ObjectAnimator anim2 = ObjectAnimator.ofFloat(view, "rotation", 1.0f, 2f); AnimatorSet animSet = new AnimatorSet(); animSet.setDuration(2000); animSet.setInterpolator(new LinearInterpolator()); // 兩個動畫同時執行 animSet.playTogether(anim1, anim2); animSet.start(); }updateView方法
//status數組決定哪個View是顯示的,visibleCount決定要顯示的數目 public void updateView(boolean[] status, int visibleCount) { Log.e("updateView", "updateView start "); mGoneView = new ArrayList<ItemView>(); mVisibledView = new ArrayList<ItemView>(); mVisiblingView = new ArrayList<ItemView>(); mVisibleView = new ArrayList<ItemView>(); itemWidth = mWidth / visibleCount;//重新計算每份的長度 Log.e("updateView", "onLayout itemWidth = " + itemWidth); Log.e("updateView", "onLayout visibleCount = " + visibleCount); int count = 0; for (int i = 0; i < status.length; i++) { final ItemView itemView = (ItemView) getChildAt(i); if (status[i])//根據boolean,這是要顯示的View { int itemWh = 0; itemWh = itemView.getWidth(); if (itemWh == 0) { itemWh = 80; } int maginLeft = itemWidth * count + (itemWidth - itemWh) / 2;//View的left坐標 count++; itemView.setmCurrentPosition(maginLeft);//保存位置信息,便于后期根據坐標做動畫 CurrentPosition Log.e("updateView", "updateView setmCurrentPosition " + maginLeft + " , i = " + i); if (itemView.getVisibility() == View.VISIBLE) { // ((ItemView)getChildAt(i)).setmLastPosition(getChildAt(i).getLeft()); Log.e("updateView", "updateView getChildAt(i).getLeft() " + itemView.getLeft() + " , i = " + i); mVisibledView.add(itemView);//已經顯示了,本來就是顯示的 } else { mVisiblingView.add(itemView);//本來沒顯示,這次要顯示的 } mVisibleView.add(itemView); } else { mGoneView.add(itemView);//本次需要隱藏的 if (itemView.getVisibility() != View.GONE) { itemView.setVisibility(View.GONE); } } } //準備完數據后開始動畫 for (int i = 0; i < mVisibleView.size(); i++) { if (mVisibledView.contains(mVisibleView.get(i))) //本來就顯示的做平移動畫 { Log.e("updateView", "updateView getChildAt(i).getmCurrentPosition() " + mVisibleView.get(i).getmCurrentPosition()); Log.e("updateView", "updateView getChildAt(i).getmLastPosition() " + mVisibleView.get(i).getmLastPosition()); ObjectAnimator .ofFloat(mVisibleView.get(i), "translationX", (mVisibleView.get(i).getmLastPosition() - mVisibleView.get(i).getmCurrentPosition()), 0f).setDuration(500).start(); } else//未顯示的setVisibility(View.VISIBLE) { mVisibleView.get(i).setVisibility(View.VISIBLE); AlphaAnimation mAlphaAnimation = new AlphaAnimation(0.0f, 1.0f); mAlphaAnimation.setDuration(200); mAlphaAnimation.setInterpolator(new AccelerateInterpolator()); mVisibleView.get(i).startAnimation(mAlphaAnimation); } } Log.e("updateView", "updateView end "); }下面是使用demo:
public class AnimationActivity extends Activity{ private Button button1 = null; private Button button2 = null; private JPowerTranslateView mJPowerTranslateView; boolean isReset = false; boolean isReset2 = false; int visibleCount = 4; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.animation_activity); mJPowerTranslateView = (JPowerTranslateView) findViewById(R.id.animation_main_view); mJPowerTranslateView.setBackgroundResource(R.drawable.lava_pro_single_settings_bg); button1 = (Button) findViewById(R.id.button1); button2 = (Button) findViewById(R.id.button2); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub boolean status[] = { true, true, false, true }; boolean reset[] = { true, true, true, true }; if (isReset) { mJPowerTranslateView.updateView(status, 3); isReset = false; } else { isReset = true; mJPowerTranslateView.updateView(reset, 4); } // mJPowerTranslateView.updateView(); } }); button2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub boolean status[] = { true, false, true, false }; boolean reset[] = { false, true, false, false }; if (isReset) { mJPowerTranslateView.updateView(status, 2); isReset = false; } else { mJPowerTranslateView.updateView(reset, 1); isReset = true; } // mJPowerTranslateView.updateView(); } }); }}JPowerTranslateView 完整代碼
import java.util.ArrayList;import java.util.List;import android.animation.Animator;import android.animation.AnimatorListenerAdapter;import android.animation.AnimatorSet;import android.animation.ObjectAnimator;import android.animation.PropertyValuesHolder;import android.animation.ValueAnimator;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.WindowManager;import android.view.animation.AccelerateInterpolator;import android.view.animation.AlphaAnimation;import android.view.animation.Animation;import android.view.animation.Animation.AnimationListener;import android.view.animation.LinearInterpolator;import android.view.animation.TranslateAnimation;import android.widget.ImageView;import android.widget.LinearLayout;public class JPowerTranslateView extends LinearLayout{ private int mDisplayWith = 720; private int mWidth = 720; private int itemWidth; int visibleCount = 4; private List<ItemView> mGoneView = null; private List<ItemView> mVisibledView = null; private List<ItemView> mVisiblingView = null; private List<ItemView> mVisibleView = null; public JPowerTranslateView(Context context) { super(context, null); } public JPowerTranslateView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public JPowerTranslateView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); mDisplayWith = wm.getDefaultDisplay().getWidth(); } //初始化 把GONE與VISIBLE的View分別放進不同的ArrayList @Override protected void onFinishInflate() { // TODO Auto-generated method stub super.onFinishInflate(); mGoneView = new ArrayList<ItemView>(); mVisibledView = new ArrayList<ItemView>(); mVisibleView = new ArrayList<ItemView>(); for (int i = 0; i < getChildCount(); i++) { if (getChildAt(i).getVisibility() == View.GONE) { mGoneView.add((ItemView) getChildAt(i)); } else { mVisibledView.add((ItemView) getChildAt(i)); mVisibleView.add((ItemView) getChildAt(i)); } } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mWidth = getMeasuredWidth(); if (mWidth == 0) { mWidth = mDisplayWith; } } //排布子View @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (mVisibleView != null && mVisibleView.size() > 0) { int visibleCount = mVisibleView.size();//需要顯示View的數量 itemWidth = mWidth / visibleCount; //等分父容器 for (int i = 0; i < visibleCount; i++) { int itemWh = 0; ItemView itemView = mVisibleView.get(i); itemWh = itemView.getWidth(); if (itemWh == 0) { itemWh = 80; } int maginLeft = itemWidth * i + (itemWidth - itemWh) / 2;//子View的left坐標,即把每個子View放置在每份的中間 itemView.layout(maginLeft, itemView.getTop(), maginLeft + itemWh, itemView.getBottom()); itemView.setmLastPosition(maginLeft);//保存位置信息,便于后期根據坐標做動畫 LastPosition } } } //status數組決定哪個View是顯示的,visibleCount決定要顯示的數目 public void updateView(boolean[] status, int visibleCount) { Log.e("updateView", "updateView start "); mGoneView = new ArrayList<ItemView>(); mVisibledView = new ArrayList<ItemView>(); mVisiblingView = new ArrayList<ItemView>(); mVisibleView = new ArrayList<ItemView>(); itemWidth = mWidth / visibleCount;//重新計算每份的長度 int count = 0; for (int i = 0; i < status.length; i++) { final ItemView itemView = (ItemView) getChildAt(i); if (status[i])//根據boolean,這是要顯示的View { int itemWh = 0; itemWh = itemView.getWidth(); if (itemWh == 0) { itemWh = 80; } int maginLeft = itemWidth * count + (itemWidth - itemWh) / 2;//View的left坐標 count++; itemView.setmCurrentPosition(maginLeft);//保存位置信息,便于后期根據坐標做動畫 CurrentPosition if (itemView.getVisibility() == View.VISIBLE) { // ((ItemView)getChildAt(i)).setmLastPosition(getChildAt(i).getLeft()); mVisibledView.add(itemView);//已經顯示了,本來就是顯示的 } else { mVisiblingView.add(itemView);//本來沒顯示,這次要顯示的 } mVisibleView.add(itemView); } else { mGoneView.add(itemView);//本次需要隱藏的 if (itemView.getVisibility() != View.GONE) { itemView.setVisibility(View.GONE); } } } //準備完數據后開始動畫 for (int i = 0; i < mVisibleView.size(); i++) { if (mVisibledView.contains(mVisibleView.get(i))) //本來就顯示的做平移動畫 { ObjectAnimator .ofFloat(mVisibleView.get(i), "translationX", (mVisibleView.get(i).getmLastPosition() - mVisibleView.get(i).getmCurrentPosition()), 0f).setDuration(500).start(); } else//未顯示的setVisibility(View.VISIBLE) { mVisibleView.get(i).setVisibility(View.VISIBLE); AlphaAnimation mAlphaAnimation = new AlphaAnimation(0.0f, 1.0f); mAlphaAnimation.setDuration(200); mAlphaAnimation.setInterpolator(new AccelerateInterpolator()); mVisibleView.get(i).startAnimation(mAlphaAnimation); } } }}新聞熱點
疑難解答