自定义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
- 自定义ViewGroup动态添加删除Tab
- Android 自定义ViewGroup 实现FlowLayout,动态添加布局
- 自定义ViewGroup动态显示添加view的位置
- Android自定义ViewGroup ,动态添加数目不确定的ImageView
- ExtJS动态添加和删除tab标签实例
- 动态添加Tab控件
- easyui 动态添加 tab
- EasyUI 动态添加tab
- Ext JS4.0中Tabpanel动态添加和删除Tab和重用Tab的方法
- Android自定义ViewGroup之子控件的自动换行和添加删除
- Android自定义ViewGroup之子控件的自动换行和添加删除
- Android自定义ViewGroup之子控件的自动换行和添加删除
- Android自定义ViewGroup之子控件的自动换行和添加删除
- Android自定义ViewGroup之子控件的自动换行和添加删除
- Android自定义ViewGroup之子控件的自动换行和添加删除
- Android自定义ViewGroup之子控件的自动换行和添加删除
- viewgroup中删除和添加子view
- viewgroup中删除和添加子view
- JS动态添加option和删除option
- postgresql dblink使用
- android rxjava的简单使用
- java内存结构和对象创建的过程
- Spring-data-redis
- 自定义ViewGroup动态添加删除Tab
- 浅谈构造函数和析构函数的调用顺序
- Docker 技巧:删除 Docker 容器和镜像
- web容器, ejb, jms 介绍
- Python(8): Lambda,列表解析器,生成器表达式,range函数
- itunes connect上传前的准备
- Android App的设计架构:MVC,MVP,MVVM与架构经验谈
- MySQL学习笔记
- 【C#】数组,集合,泛型