自定义ViewGroup动态添加删除Tab

来源:互联网 发布:希区柯克剧场 知乎 编辑:程序博客网 时间:2024/05/01 04:07

公司的手机OS升级,在最新的Camera拟用这样的交互。感觉还不错。
这里写图片描述
思路:
1.ViewGroup中包含imageView按钮,根据显示的个数动态计算布局,在onLayout中重新排布ImageView的位置。
2.重新排布ImageView的位置的时候使用动画,动画需要坐标即需要自定义ImageView添加位置属性。
3.提供给外界方法用以决定显示哪个按钮,显示几个。

下面先来给imageView控件添加坐标属性。
public class ItemView extends ImageView{    private int mLastStaus = View.VISIBLE;    private float mLastPosition = 0;    private float mCurrentPosition = 0;    public ItemView(Context context, AttributeSet attrs, int defStyle)    {        super(context, attrs, defStyle);            }    public ItemView(Context context, AttributeSet attrs)    {        super(context, attrs);      }    public ItemView(Context context)    {        super(context);         }    public float getmLastPosition()    {        return mLastPosition;    }    public void setmLastPosition(float mLastPosition)    {        this.mLastPosition = mLastPosition;    }    /**     * @return the mLastStaus     */    public int getmLastStaus()    {        return mLastStaus;    }    /**     * @param mLastStaus the mLastStaus to set     */    public void setmLastStaus(int mLastStaus)    {        this.mLastStaus = mLastStaus;    }    /**     * @return the mCurrentPosition     */    public float getmCurrentPosition()    {        return mCurrentPosition;    }    /**     * @param mCurrentPosition the mCurrentPosition to set     */    public void setmCurrentPosition(float mCurrentPosition)    {        this.mCurrentPosition = mCurrentPosition;    }}    

现在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);            }        }    }}
0 0
原创粉丝点击