一个带动画的页面底部的TabBar的实现

有时有这样一个需求,页面底部有几个图标能够点击,假设一个screenWidth显示不下这些图标,则这一列图标最后一个是more,点击more,能够通过动画展示两列图标

这样来增加layout中:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#FFFFFF" >

        <include
            android:id="@+id/title"
            layout="@layout/title_list" />

        <View
            android:id="@+id/line"
            android:layout_width="fill_parent"
            android:layout_height="2dip"
            android:layout_below="@id/title"
            android:background="@drawable/rc_list_divider" />

        <ListView
            android:id="@+id/mylist"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/title"
            android:background="@null"
            android:cacheColorHint="@color/bgColorMain"
            android:divider="@null"
            android:dividerHeight="0dp"
            android:fadeScrollbars="false"
            android:visibility="gone" >
        </ListView>

        <LinearLayout
            android:id="@+id/loading_layout"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_below="@id/line"
            android:background="@color/white"
            android:gravity="center" >

            <ProgressBar
                style="?android:attr/progressBarStyleLarge"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom" >

       <strong> <com.example.view.ExpandableView
            android:id="@+id/launcher_expand_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" /></strong>
    </RelativeLayout>

</FrameLayout>

代码里这样来写:

private void prepareLauncherView() {

		mRootView = LayoutInflater.from(this).inflate(R.layout.activity_main, null);
		setContentView(mRootView);

		DisplayMetrics dm = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(dm);
		int screenWidth = dm.widthPixels;
		int height = dm.heightPixels;
		//取出底部几个Button的图标资源
		mLauncherDrawables = getResources().obtainTypedArray(R.array.launcher_item_drawables);

		mExpandableView = (ExpandableView) findViewById(R.id.launcher_expand_view);
		mItemViews = new ArrayList<View>();
		for (int i = 0; i < mLauncherDrawables.length(); i++) {
			addLauncherItem(i);
		}
		//点击more的时候响应(运行TransLate动画)
		mExpandableView.setOnExpandItemClickListener(this);

		int contentHeight = height - getStatusBarHeight();
		mExpandableView.setScreenSize(contentHeight, screenWidth);
		mExpandableView.addListView(mItemViews);

	}	

	@Override
	protected void onStart() {
		super.onStart();
		mExpandableView.setRestart(true);
	}

	private int getStatusBarHeight() {  <strong>//这个是取statusbar高度的做法</strong>

		Class<?

> c = null;
		Object obj = null;
		Field field = null;
		int x = 0, sbar = 0;
		try {

			c = Class.forName("com.android.internal.R$dimen");
			obj = c.newInstance();
			field = c.getField("status_bar_height");
			x = Integer.parseInt(field.get(obj).toString());
			sbar = getResources().getDimensionPixelSize(x);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		return sbar;
	}

	private void addLauncherItem(int i) {
		View view = LayoutInflater.from(this).inflate(R.layout.launch_bar_item, null).findViewById(R.id.launcher_content);
		view.setBackgroundDrawable(mLauncherDrawables.getDrawable(i));
		mItemViews.add(view);
	}

	@Override
	public void onExpandItemClick(View parentView, View view, int position, int maxNum, int line) {
		if (!mExpandableView.isInAnimation()) {
			if (position != maxNum) {
				mExpandableView.excuteAnimation(false);
			} else {
				mExpandableView.excuteAnimation(true);
			}
		}
	}

关于ExpandableView这个类:

package com.example.view;

import java.util.List;

import com.example.shoplistdownload.R;

import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.view.animation.Animation.AnimationListener;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;

public class ExpandableView extends LinearLayout {

	private int mScreenWidth;
	private int mScreenHeight;
	private int mButtonWidth;
	private int mButtonHeight;
	private LinearLayout mLayoutShow;
	private LinearLayout mLayoutHide;
	private ExpandItemClickListener onExpandItemClickListener;
	private int mMaxNum;
	private boolean mIsInAnimation = false;
	private boolean mCanMoveToBottom = false;
	private View mMoreView;
	private int mOldBottom;
	private Context mContext;
	private int mHeaderHeight;
	private double mAverageSize;
	private boolean mIsFirstLayout= true;
	private LinearLayout.LayoutParams mParams;
	private boolean mRestart = false;
	private LayoutInflater mInflater;
	public static final int LAUNCHER_BAR_LINE_ONE = 0;
	public static final int LAUNCHER_BAR_LINE_TWO = 1;

	private static final boolean LAUNCHER_HIDE_LAYOUT_TAG = true;

	public ExpandableView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mContext = context;
		mInflater = LayoutInflater.from(mContext);
	}

	public void setScreenSize(int height, int width) {
		mScreenHeight = height;
		mScreenWidth = width;
		initParameter();
		initSubView();
	}

	private void initParameter(){
		mButtonWidth = mContext.getResources().getDimensionPixelSize(R.dimen.expand_item_minwidth);
		mButtonHeight = mContext.getResources().getDimensionPixelSize(R.dimen.expand_item_minheight);
		mHeaderHeight = mContext.getResources().getDimensionPixelSize(R.dimen.header_bar_height);
		mMaxNum = mScreenWidth / mButtonWidth;
		mAverageSize = ((double) mScreenWidth) / mMaxNum;
		this.setOrientation(LinearLayout.VERTICAL);
	}

	public void addListView(List<View> views) {
		setPortraitView(views);
		//mLayoutShow为第一列
		addView(mLayoutShow);
		//mLayoutHide为第二列,第一次展示时会隐藏
		addView(mLayoutHide);

	}

	private void initSubView() {
		mMoreView = mInflater.inflate(R.layout.launch_bar_item, null).findViewById(R.id.launcher_content);
		mMoreView.setBackgroundResource(R.drawable.btn_launcher_more);
		mMoreView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				mRestart = false;
				onExpandItemClickListener.onExpandItemClick(mLayoutShow, v, mMaxNum, mMaxNum, LAUNCHER_BAR_LINE_ONE);
			}
		});

		mLayoutShow = new LinearLayout(mContext);
		mLayoutHide = new LinearLayout(mContext);
		mLayoutHide.setTag(LAUNCHER_HIDE_LAYOUT_TAG);
		mParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, mButtonHeight);
		mLayoutShow.setOrientation(LinearLayout.HORIZONTAL);
		mLayoutHide.setOrientation(LinearLayout.HORIZONTAL);
		mLayoutShow.setBackgroundResource(R.drawable.bg_launcher_port_nor);
		mLayoutHide.setBackgroundResource(R.drawable.bg_launcher_port_nor);
		mLayoutShow.setLayoutParams(mParams);
		mLayoutHide.setLayoutParams(mParams);
	}

	private void setPortraitView(List<View> views) {
		if (views.size() > mMaxNum) {
			//将底部Button增加mLayoutShow和mLayoutHide
			mLayoutShow = adjustPortraitView(mLayoutShow, 0, mMaxNum - 1, views, true);
			mLayoutHide = adjustPortraitView(mLayoutHide, mMaxNum - 1, views.size(), views, false);
		} else {
			//假设底部图标数比較少,那么mLayoutHide就永远隐藏
			mLayoutHide.setVisibility(View.GONE);
			mLayoutShow = adjustPortraitView(mLayoutShow, 0, views.size(), views, false);
		}
	}

	private LinearLayout adjustPortraitView(LinearLayout layout, int start, int end, List<View> views, boolean isAddMore) {
		for (int i = start; i < end; i++) {
			final View view = views.get(i);
			view.setLayoutParams(new LayoutParams((int) mAverageSize, LayoutParams.FILL_PARENT));
			view.setTag(i);
			setClick(layout, view, LAUNCHER_BAR_LINE_ONE);
			layout.addView(view);
		}
		if (isAddMore) {
			mMoreView.setLayoutParams(new LayoutParams((int)mAverageSize, LayoutParams.FILL_PARENT));
			mLayoutShow.addView(mMoreView);
		}
		return layout;
	}

	private void setClick(final LinearLayout layout, final View view, final int line) {
		view.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				mRestart = false;
				if (onExpandItemClickListener != null) {
					onExpandItemClickListener.onExpandItemClick(layout, view, (Integer) view.getTag(), mMaxNum, line);
				}
			}
		});
	}

	public boolean isInAnimation() {
		return mIsInAnimation;
	}

	public boolean isCanMoveToBottom(){
		//这里依据getBottom来推断页面仅仅是展示mLayoutShow或是同一时候展示mLayoutShow和mLayoutHide
		//假设getBottom() < mOldBottom,这个时候就是页面仅仅有mlayoutShow,由于mLayoutShow和mLayoutHide同一时候存在时显然getBottom比較大
		if (mLayoutHide != null && mLayoutHide.getVisibility() == View.VISIBLE) {
			int bottom = this.getBottom();
			if (bottom > mOldBottom) {
				mCanMoveToBottom = false;
			} else if(bottom <= mOldBottom) {
				mCanMoveToBottom = true;
			}
		}
		return mCanMoveToBottom;
	}

	public void excuteAnimation(boolean isClickMore) {
		if (mLayoutHide != null && mLayoutHide.getVisibility() == View.VISIBLE) {
			if (!mIsInAnimation) {
				if (isCanMoveToBottom()) {
					mIsInAnimation = true;
					mMoreView.setSelected(false);
					//这个动画是向下的
					this.startAnimation(getAnimation(true, 0, 0, 0, mButtonHeight));
					mCanMoveToBottom = false;
				} else {
					if (isClickMore) {
						mIsInAnimation = true;
						mMoreView.setSelected(true);
						//这个动画是向上的
						this.startAnimation(getAnimation(false, 0, 0, 0, -mButtonHeight));
						mCanMoveToBottom = true;
					}
				}
			}
		}
	}

	private Animation getAnimation(final boolean moToBottom, int fromXDelta, final int toXDelta,
			int fromYDelta, final int toYDelta) {
		TranslateAnimation animation = new TranslateAnimation(fromXDelta,
				toXDelta, fromYDelta, toYDelta);
		animation.setDuration(200);
		animation.setFillAfter(true);
		animation.setAnimationListener(new AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {
			}

			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public void onAnimationEnd(Animation animation) {
				ExpandableView.this.clearAnimation();
				ExpandableView.this.layout(ExpandableView.this.getLeft(),
						(ExpandableView.this.getTop() + toYDelta),
						ExpandableView.this.getRight(),
						(ExpandableView.this.getBottom() + toYDelta));
				mIsInAnimation = false;
			}
		});
		return animation;
	}

	public void setOnExpandItemClickListener(ExpandItemClickListener listener) {
		onExpandItemClickListener = listener;
	}

	public interface ExpandItemClickListener {
		void onExpandItemClick(final View parentView, View view, int position, int maxNum, int line);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if (mLayoutHide != null && mLayoutHide.getVisibility() == View.VISIBLE) {
			if(mIsFirstLayout && this.getWidth() > 0){
				mIsFirstLayout = false;
				mOldBottom = this.getBottom();
				this.layout(this.getLeft(), (this.getTop() + mHeaderHeight), this.getRight(), (this.getBottom() + mHeaderHeight));
			}
			//假设是第一次显示该view,mLayoutHide是不显示的
			if (mRestart && this.getBottom() <= mOldBottom && !mIsFirstLayout) {
				this.layout(this.getLeft(), (this.getTop() + mHeaderHeight), this.getRight(), (this.getBottom() + mHeaderHeight));
			}
		}
	}

	public void setRestart(boolean restart){
		mRestart = restart;
	}

}

代码:http://download.csdn.net/download/baidu_nod/7748987

时间: 2024-12-22 08:43:42

一个带动画的页面底部的TabBar的实现的相关文章

IOS的一个带动画的多项选择的控件(二)

然后我们来写:TypeSelectView 这个比较简单,我们只要只要每个TypeView的位置,然后作为自己的subview就好了 @interface TypeSelectView : UIView @property(nonatomic) BOOL bShown; @property(nonatomic, strong) TypeView* curSelectedView; -(id)initWithFrame:(CGRect)frame searchType:(int)type; @en

IOS的一个带动画的多项选择的控件(一)

先上效果图: 这个程序分2个层次,一个是顶部的带UITextField的bar,一个是下拉选择的view,下拉选择的view带有4个自定义的UIView 我们先定义一个UIViewController叫MyViewController,然后顶部的bar叫TopBarView,下拉选择的view叫TypeSelectView,像UIButton的自定义的view叫做TypeView TypeView有两种状态,如果手指触摸到的item就是选中状态,所以TypeSelectView应该有个属性表示当

一个带动画的dialog

根据项目需求需要在加载的时候加入一个带动画效果的进度. 最先想到的就是 自定义一个dialog 再加上一个动画就OK了. so..... public class CMYProgressDialog extends Dialog { public CMYProgressDialog(Context context) { super(context, R.style.CMYProgressDialog); setContentView(R.layout.layout_loading); getWi

收藏一个带动画效果的ScrollViewer以及ScrollBar的模板

原文:收藏一个带动画效果的ScrollViewer以及ScrollBar的模板 这里介绍一个带动画效果的ScrollViewer和ScrollBar,总共分为两个资源字典,直接拿来引用即可: 1 ScrollBarStyle.xaml <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft

iOS使用push隐藏子页面底部bottom TabBar

以下两种情况是我在开发过程中遇到的,一种是代码使用pushViewController,另一种是storyboard直接使用push.之前也查阅了很多关于隐藏底部tabbar的资料,但是要么使用起来麻烦,要么就是藕合度高代码不规范(这里有点代码洁癖,当前类相关的事务应该写在本类中). 1.使用pushViewController 如A->B;A是列表页,带有tabbar:B是内容页,不需要tabbar: 在A的事件中打开B,如下代码 -(void)showVideo:(EJAlbumModel

一个带动画效果的颜色选择对话框控件AnimatedColorPickerDialog

android4.4的日历中选择日程显示颜色的时候有一个颜色选择对话框非常漂亮,模仿他的界面我实现了一个类似的对话框,而且带有动画效果. 代码的实现可讲的地方不多,主要是采用了和AlertDialog类似的Builder方式来创建对话框,另外当每个颜色被选择的时候有个按下效果是用纯代码实现的,还有就是可以动态的判断一排可以显示多少个颜色元素.而动画效果我们是使用属性动画实现,如果要做到兼容2.3需要使用第三方库NineOldAndroids来实现属性动画. 源码如下: 1 2 3 4 5 6 7

一个带动画效果的颜色对话框控件AnimatedColorPickerDialog

android4.4的日历中选择日程显示颜色的时候有一个颜色选择对话框非常漂亮,模仿他的界面我实现了一个类似的对话框,而且带有动画效果. 代码的实现可讲的地方不多,主要是采用了和AlertDialog类似的Builder方式来创建对话框,另外当每个颜色被选择的时候有个按下效果 是用纯代码实现的,还有就是可以动态的判断一排可以显示多少个颜色元素.而动画效果我们是使用属性动画实现,如果要做到兼容2.3需要使用第三方库 NineOldAndroids来实现属性动画. 源码如下: package com

纯css写一个带动画的弹框 visibility + opcity

css能实现各种各样的动态效果,比js实现简单,性能也比js实现高,现在我们就用纯css实现弹窗,主要用到了两个属性 opcity 和 visibility, opctiy 这个属性很简单 控制元素透明度 ,visibility控制元素的显示和隐藏,他和display有一个很重要的区别,visibility可以用transition来进行过渡,而display并不可以,这就是我们不用display的原因 可以配合上transform: scale() 让弹窗更有动态感觉 全部代码: <!DOCT

07---关于动态创建和销毁带动画的UIVew

在我们做开发的过程中经常会遇到在你触发了某个动作之后,需要动态添加一个带动画的UIView,执行完以后就销毁这个UIView #pragma mark 展示最新微博的数目 - (void)showNewStatusCount:(int)count { // 1.创建按钮 UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; btn.enabled = NO; // 设置按钮禁用 btn.adjustsImageWhenDisa