有时有这样一个需求,页面底部有几个图标能够点击,假设一个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

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

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

    这里介绍一个带动画效果的ScrollViewer和ScrollBar,总共分为两个资源字典,直接拿来引用即可: 1 ScrollBarStyle.xaml <ResourceDictionary ...

  2. 利用css transition属性实现一个带动画显隐的微信小程序部件

    我们先来看效果图 像这样的一个带过渡效果的小部件在我们实际开发中的应用几率还是比较大的,但是在开发微信小程序的过程中可能有的小伙伴发现transition这个属性它不好使(下面说明)所以我们这个时候会 ...

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

    下面两种情况是我在开发过程中遇到的,一种是代码使用pushViewController,还有一种是storyboard直接使用push.之前也查阅了非常多关于隐藏底部tabbar的资料.可是要么使用起 ...

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

    先上效果图: 这个程序分2个层次,一个是顶部的带UITextField的bar,一个是下拉选择的view,下拉选择的view带有4个自己定义的UIView 我们先定义一个UIViewControlle ...

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

    android4.4的日历中选择日程显示颜色的时候有一个颜色选择对话框非常漂亮,模仿他的界面我实现了一个类似的对话框,而且带有动画效果. 代码的实现可讲的地方不多,主要是采用了和AlertDialog ...

  6. 兼容IE6的页面底部固定层CSS代码

    有时候当我们需要把一个元素固定在页面的某个部位,一般都是用css中的“position:fixed;”方法来解决,但是IE6不支持fixed,所以今天分享一个兼容IE6的页面底部固定层CSS代码.如下 ...

  7. Android开发:带动画的分享效果

    这几天做了个带动画的分享页面.如今把它分享出来,假设你认为实用,请直接使用,避免反复造轮子 先看下效果图 认为仅仅是看效果图不明显.那么用手机扫描以下的二维码下载安装包:

  8. jquery插件——点击交换元素位置(带动画效果)

    一.需求的诞生 在我们的网页或者web应用中,想要对列表中的元素进行位置调整(或者说排序)是一个常见的需求.实现方式大概就以下两种,一种是带有类似“上移”.“下移”的按钮,点击可与相邻元素交换位置,另 ...

  9. jQuery之锚点带动画跳转特效

    背景图片为金木研,这是我最爱的一张图. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...

随机推荐

  1. Bigcommerce:安装的出错解决方案

    我们在本地安装时报错了,具体如下: 1. The database details you entered are incorrect: You have an error in your SQL s ...

  2. 利用JS跨域做一个简单的页面訪问统计系统

    事实上在大部分互联网web产品中,我们一般会用百度统计或者谷歌统计分析系统,通过在程序中引入特定的JS脚本,然后便能够在这些统计系统中看到自己站点页面详细的訪问情况.可是有些时候,因为一些特殊情况,我 ...

  3. [Machine Learning (Andrew NG courses)]IV.Linear Regression with Multiple Variables

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenFoXzE5OTE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA ...

  4. 邮件应用Acompli和日历应用Sunrise(传微软曾考虑以80亿美元收购企业通讯公司Slack)

    http://tech.163.com/16/0305/10/BHCU8EHO000915BD.html http://www.cnbeta.com/articles/480835.htm

  5. Qt中使用定时器(可使用QObject::timerEvent定时执行,QTimer::singleShot可只触发一次)

    在Qt中使用定时器有两种方法,一种是使用QObiect类的定时器:一种是使用QTimer类.定时器的精确性依赖于操作系统和硬件,大多数平台支持20ms的精确度 1.QObject类的定时器 QObje ...

  6. 与众不同 windows phone (4) - Launcher(启动器)

    原文:与众不同 windows phone (4) - Launcher(启动器) [索引页][源码下载] 与众不同 windows phone (4) - Launcher(启动器) 作者:weba ...

  7. 轻松学会多线程(四)——synchronized同步keyword知多少

    每个对象都有一把独占锁. 独占锁仅仅限制线程对它的同步方法的訪问,对非同步方法,独占锁没有意义. synchronizedkeyword能够作为函数的修饰符,也能够作为函数内的语句,也就是平时说的同步 ...

  8. 使用Android简单实现有道电子词典

    前言: 毕业设计的内容,仅仅有Java基础.没学过Android. 本着用到什么学什么.花费了10多个晚上完毕毕业设计. 当然,仅仅是简单的实线了电子词典功能,自始至终没有考虑过性能等问题. 本电子词 ...

  9. ORA-00376:file x cannot be read at this time

    之前出现过机房断电情况,重启数据库后发现出现ORA-00376的错误. 通过查询数据文件状态: SQL> select file_id,online_status from dba_data_f ...

  10. stm32 ARM中的RO、RW和ZI DATA

    一直以来对于ARM体系中所描述的RO,RW和ZI数据存在似是而非的理解,这段时间对其仔细了解了一番,发现了一些规律,理解了一些以前书本上有的但是不理解的东西,我想应该有不少人也有和我同样的困惑,因此将 ...