一个带动画的页面底部的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;
} }
一个带动画的页面底部的TabBar的实现的更多相关文章
- 收藏一个带动画效果的ScrollViewer以及ScrollBar的模板
这里介绍一个带动画效果的ScrollViewer和ScrollBar,总共分为两个资源字典,直接拿来引用即可: 1 ScrollBarStyle.xaml <ResourceDictionary ...
- 利用css transition属性实现一个带动画显隐的微信小程序部件
我们先来看效果图 像这样的一个带过渡效果的小部件在我们实际开发中的应用几率还是比较大的,但是在开发微信小程序的过程中可能有的小伙伴发现transition这个属性它不好使(下面说明)所以我们这个时候会 ...
- iOS使用push隐藏子页面底部bottom TabBar
下面两种情况是我在开发过程中遇到的,一种是代码使用pushViewController,还有一种是storyboard直接使用push.之前也查阅了非常多关于隐藏底部tabbar的资料.可是要么使用起 ...
- IOS的一个带动画的多项选择的控件(一)
先上效果图: 这个程序分2个层次,一个是顶部的带UITextField的bar,一个是下拉选择的view,下拉选择的view带有4个自己定义的UIView 我们先定义一个UIViewControlle ...
- 一个带动画效果的颜色选择对话框控件AnimatedColorPickerDialog
android4.4的日历中选择日程显示颜色的时候有一个颜色选择对话框非常漂亮,模仿他的界面我实现了一个类似的对话框,而且带有动画效果. 代码的实现可讲的地方不多,主要是采用了和AlertDialog ...
- 兼容IE6的页面底部固定层CSS代码
有时候当我们需要把一个元素固定在页面的某个部位,一般都是用css中的“position:fixed;”方法来解决,但是IE6不支持fixed,所以今天分享一个兼容IE6的页面底部固定层CSS代码.如下 ...
- Android开发:带动画的分享效果
这几天做了个带动画的分享页面.如今把它分享出来,假设你认为实用,请直接使用,避免反复造轮子 先看下效果图 认为仅仅是看效果图不明显.那么用手机扫描以下的二维码下载安装包:
- jquery插件——点击交换元素位置(带动画效果)
一.需求的诞生 在我们的网页或者web应用中,想要对列表中的元素进行位置调整(或者说排序)是一个常见的需求.实现方式大概就以下两种,一种是带有类似“上移”.“下移”的按钮,点击可与相邻元素交换位置,另 ...
- jQuery之锚点带动画跳转特效
背景图片为金木研,这是我最爱的一张图. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...
随机推荐
- 基于visual Studio2013解决面试题之0304镜像二叉树
题目
- Js三级联动菜单
效果演示: <SCRIPT LANGUAGE="JavaScript"> <!-- function CreateSelect(_FormName,_SName, ...
- SilkTest Q&A 11
101. 如何从其他的机器访问脚本? 答案:将包含脚本的文件夹共享出来…非常简单…你可以使用connect()在你本机运行脚本从而使得它们在其他的一些机器上执行…但是其他人无法访问这些脚本,除非你将它 ...
- SQL server语句练习
相关表: <span style="white-space:pre">create table DEPT ( <span style="white-sp ...
- Linux通配符摘要
参考<鸟哥linux私房菜> * - 通配符,代表随机字符(0对于许多) ? - 通配符,它代表一个字符 # - 凝视 / - 跳转符号,将特殊字符或通配符还原成一般符号 | - 分隔两个 ...
- 深入探讨MFC消息循环和消息泵
首先,应该清楚MFC的消息循环(::GetMessage,::PeekMessage),消息泵(CWinThread::PumpMessage)和MFC的消息在窗口之间的路由是两件不同的事情.在MFC ...
- 【ASP.NET Web API教程】4.1 ASP.NET Web API中的路由
原文:[ASP.NET Web API教程]4.1 ASP.NET Web API中的路由 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. ...
- JAVA WEB开发环境搭建教程
一.下载安装JDK,配置好环境变量.(例如我JDK安装的目录为:C:\Program Files (x86)\Java\jdk1.6.0_10 ) 点击我的电脑-属性-系统设置(高级系统设置) ...
- No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=arm64, VALID_ARCHS=armv7 armv7s)
问题: No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=arm64, VALID_ARCHS=armv7 armv ...
- JavaBean在DAO设计模式简介
一.信息系统开发框架 客户层-------显示层-------业务层---------数据层---------数据库 1.客户层:客户层是client,简单的来说就是浏览器. 2.显示层:JSP/Se ...