android一个弹出菜单的动画(二)
假设做一个弹出的控件,我们能够进行加入view:
写class SatelliteMenu extends FrameLayout
private void init(Context context, AttributeSet attrs, int defStyle) {
inflate(context, R.layout.sat_main, this);
imgMain = (ImageView) findViewById(R.id.sat_main);
if(attrs != null){
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SatelliteMenu, defStyle, 0);
satelliteDistance = typedArray.getDimensionPixelSize(R.styleable.SatelliteMenu_satelliteDistance, DEFAULT_SATELLITE_DISTANCE);
totalSpacingDegree = typedArray.getFloat(R.styleable.SatelliteMenu_totalSpacingDegree, DEFAULT_TOTAL_SPACING_DEGREES);
closeItemsOnClick = typedArray.getBoolean(R.styleable.SatelliteMenu_closeOnClick, DEFAULT_CLOSE_ON_CLICK);
expandDuration = typedArray.getInt(R.styleable.SatelliteMenu_expandDuration, DEFAULT_EXPAND_DURATION);
//float satelliteDistance = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 170, getResources().getDisplayMetrics());
typedArray.recycle();
}
mainRotateLeft = SatelliteAnimationCreator.createMainButtonAnimation(context);
mainRotateRight = SatelliteAnimationCreator.createMainButtonInverseAnimation(context);
Animation.AnimationListener plusAnimationListener = new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
plusAnimationActive.set(false);
}
};
mainRotateLeft.setAnimationListener(plusAnimationListener);
mainRotateRight.setAnimationListener(plusAnimationListener);
imgMain.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SatelliteMenu.this.onClick();
}
});
internalItemClickListener = new InternalSatelliteOnClickListener(this);
}
<? xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:id="@+id/sat_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/sat_main"
android:layout_gravity="bottom|left"
/>
</merge> <resources>
<declare-styleable name="SatelliteMenu">
<attr name="expandDuration" format="integer" />
<attr name="closeOnClick" format="boolean" />
<attr name="totalSpacingDegree" format="float" />
<attr name="satelliteDistance" format="dimension" />
<attr name="mainImage" format="reference" />
</declare-styleable>
</resources>
然后写加入Item的逻辑:
public void addItems(List<SatelliteMenuItem> items) {
menuItems.addAll(items);
this.removeView(imgMain);
TextView tmpView = new TextView(getContext());
tmpView.setLayoutParams(new FrameLayout.LayoutParams(0, 0));
float[] degrees = getDegrees(menuItems.size());
int index = 0;
for (SatelliteMenuItem menuItem : menuItems) {
int finalX = SatelliteAnimationCreator.getTranslateX(
degrees[index], satelliteDistance);
int finalY = SatelliteAnimationCreator.getTranslateY(
degrees[index], satelliteDistance);
ImageView itemView = (ImageView) LayoutInflater.from(getContext())
.inflate(R.layout.sat_item_cr, this, false);
ImageView cloneView = (ImageView) LayoutInflater.from(getContext())
.inflate(R.layout.sat_item_cr, this, false);
itemView.setTag(menuItem.getId());
cloneView.setVisibility(View.GONE);
itemView.setVisibility(View.GONE);
cloneView.setOnClickListener(internalItemClickListener);
cloneView.setTag(Integer.valueOf(menuItem.getId()));
FrameLayout.LayoutParams layoutParams = getLayoutParams(cloneView);
layoutParams.bottomMargin = Math.abs(finalY);
layoutParams.leftMargin = Math.abs(finalX);
cloneView.setLayoutParams(layoutParams);<strong>//这里是将cloneView置于itemview动画结束的位置</strong>
if (menuItem.getImgResourceId() > 0) {
itemView.setImageResource(menuItem.getImgResourceId());
cloneView.setImageResource(menuItem.getImgResourceId());
} else if (menuItem.getImgDrawable() != null) {
itemView.setImageDrawable(menuItem.getImgDrawable());
cloneView.setImageDrawable(menuItem.getImgDrawable());
}
Animation itemOut = SatelliteAnimationCreator.createItemOutAnimation(getContext(), index,expandDuration, finalX, finalY);
Animation itemIn = SatelliteAnimationCreator.createItemInAnimation(getContext(), index, expandDuration, finalX, finalY);
Animation itemClick = SatelliteAnimationCreator.createItemClickAnimation(getContext());
menuItem.setView(itemView);
menuItem.setCloneView(cloneView);
menuItem.setInAnimation(itemIn);
menuItem.setOutAnimation(itemOut);
menuItem.setClickAnimation(itemClick);
menuItem.setFinalX(finalX);
menuItem.setFinalY(finalY);
itemIn.setAnimationListener(new SatelliteAnimationListener(itemView, true, viewToItemMap));
itemOut.setAnimationListener(new SatelliteAnimationListener(itemView, false, viewToItemMap));
itemClick.setAnimationListener(new SatelliteItemClickAnimationListener(this, menuItem.getId()));
this.addView(itemView);
this.addView(cloneView);
viewToItemMap.put(itemView, menuItem);
viewToItemMap.put(cloneView, menuItem);
index++;
}
this.addView(imgMain);
}
监听器:
private static class SatelliteAnimationListener implements Animation.AnimationListener {
private WeakReference<View> viewRef;
private boolean isInAnimation;
private Map<View, SatelliteMenuItem> viewToItemMap;
public SatelliteAnimationListener(View view, boolean isIn, Map<View, SatelliteMenuItem> viewToItemMap) {
this.viewRef = new WeakReference<View>(view);
this.isInAnimation = isIn;
this.viewToItemMap = viewToItemMap;
}
@Override
public void onAnimationStart(Animation animation) {
if (viewRef != null) {
View view = viewRef.get();
if (view != null) {
SatelliteMenuItem menuItem = viewToItemMap.get(view);
if (isInAnimation) {
menuItem.getView().setVisibility(View.VISIBLE);
menuItem.getCloneView().setVisibility(View.GONE);
} else {
menuItem.getCloneView().setVisibility(View.GONE);
menuItem.getView().setVisibility(View.VISIBLE);
}
}
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if (viewRef != null) {
View view = viewRef.get();
if (view != null) {
SatelliteMenuItem menuItem = viewToItemMap.get(view);
if (isInAnimation) {
menuItem.getView().setVisibility(View.GONE);
menuItem.getCloneView().setVisibility(View.GONE);
} else {
menuItem.getCloneView().setVisibility(View.VISIBLE);
menuItem.getView().setVisibility(View.GONE);
}
}
}
}
}
必须重写onMeature:
private void recalculateMeasureDiff() {
int itemWidth = 0;
if (menuItems.size() > 0) {
itemWidth = menuItems.get(0).getView().getWidth();
}
measureDiff = Float.valueOf(satelliteDistance * 0.2f).intValue()
+ itemWidth;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
recalculateMeasureDiff();
int totalHeight = imgMain.getHeight() + satelliteDistance + measureDiff;
int totalWidth = imgMain.getWidth() + satelliteDistance + measureDiff;
System.out.println("====totalWidth="+totalWidth+"height="+totalHeight+"measureDiff="+measureDiff+"imgMain.getWidth()="+imgMain.getWidth());
setMeasuredDimension(totalWidth, totalHeight);
}
save和恢复activity的状态:
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.rotated = rotated;
ss.totalSpacingDegree = totalSpacingDegree;
ss.satelliteDistance = satelliteDistance;
ss.measureDiff = measureDiff;
ss.expandDuration = expandDuration;
ss.closeItemsOnClick = closeItemsOnClick;
return ss;
} @Override
protected void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
rotated = ss.rotated;
totalSpacingDegree = ss.totalSpacingDegree;
satelliteDistance = ss.satelliteDistance;
measureDiff = ss.measureDiff;
expandDuration = ss.expandDuration;
closeItemsOnClick = ss.closeItemsOnClick; super.onRestoreInstanceState(ss.getSuperState());
} static class SavedState extends BaseSavedState {
boolean rotated;
private float totalSpacingDegree;
private int satelliteDistance;
private int measureDiff;
private int expandDuration;
private boolean closeItemsOnClick; SavedState(Parcelable superState) {
super(superState);
} public SavedState(Parcel in) {
super(in);
rotated = Boolean.valueOf(in.readString());
totalSpacingDegree = in.readFloat();
satelliteDistance = in.readInt();
measureDiff = in.readInt();
expandDuration = in.readInt();
closeItemsOnClick = Boolean.valueOf(in.readString());
} @Override
public int describeContents() {
return 0;
} @Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(Boolean.toString(rotated));
out.writeFloat(totalSpacingDegree);
out.writeInt(satelliteDistance);
out.writeInt(measureDiff);
out.writeInt(expandDuration);
out.writeString(Boolean.toString(closeItemsOnClick));
} public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
} public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
效果图:
android一个弹出菜单的动画(二)的更多相关文章
- android一个弹出菜单的动画(一)
先上效果图: 先写Layout文件: <?xml version="1.0" encoding="utf-8"? > <RelativeLay ...
- 获得其他程序弹出菜单的内容(一个困扰许久的问题o(╯□╰)o)
刚开始到现在公司的时候接到一个任务:开发一个activex控件,自动操作本地exe程序,当时遇到弹出菜单无法获取的问题,还好不影响,最近又遇到这个问题,绕不过去了,于是昨天花了一个上午百度了个遍,总算 ...
- 关于MFC主菜单和右键弹出菜单
一.主菜单.弹出菜单和右键菜单的概念: 主菜单是窗口顶部的菜单,一个窗口或对话框只能有一个主菜单,但是主菜单可以被更改(SetMenu()更改): 创建方式:CMenu::CreateMenu(voi ...
- IOS实现弹出菜单效果MenuViewController(背景 景深 弹出菜单)
在写项目时,要实现一个从下移上来的一个弹出菜单,并且背景变深的这么一个效果,在此分享给大家. 主要说一下思路及一些核心代码贴出来,要想下载源码, 请到:http://download.csdn.net ...
- win32进阶之路:程序托盘图标+右键弹出菜单
开场白 本次介绍两个非常棒且实用的技巧:程序托盘图标和右键弹出菜单,效果如下图. 程序托盘图标用了迅雷的图标,右键点击时候会弹出三个选项的菜单. 程序托盘图标设置 我会用尽可能清晰明了的步骤介绍方式 ...
- Mui --- 弹出菜单
mui框架内置了弹出菜单插件,弹出菜单显示内容不限,但必须包裹在一个含.mui-popover类的div中,如下即为一个弹出菜单内容: <div id="popover" c ...
- [译]GLUT教程 - 弹出菜单基础
Lighthouse3d.com >> GLUT Tutorial >> Pop-up Menus >> Popup Menus 弹出菜单也是GLUT的一部分.虽然 ...
- 【Android UI设计与开发】7.底部菜单栏(四)PopupWindow 实现显示仿腾讯新闻底部弹出菜单
前一篇文章中有用到 PopupWindow 来实现弹窗的功能.简单介绍以下吧. 官方文档是这样解释的:这就是一个弹出窗口,可以用来显示一个任意视图.出现的弹出窗口是一个浮动容器的当前活动. 1.首先来 ...
- 【Android】创建Popwindow弹出菜单的两种方式
方法一的Activity package com.app.test02; import android.app.Activity; import android.os.Bundle; import a ...
随机推荐
- foundation 框架 NSString常用总结(二)
以此作为NSString常用总结(一)的补充 NSString* str = [NSString stringWithFormat:@"I love programing! You, com ...
- java的IO流包装不当导致从网页获取的数据出现乱码
从网页上获取数据时必须要注意字符集的问题.处理不慎确实苦不堪言. 例如通过URL连接时,将字节流InputStream包装成字符流(以便直接存为String)时,一定要注意加上charsetName这 ...
- fitnesse 中各类fit fixture的python实现
虽然网上都说slim效率很高,无奈找不到支持python的方法,继续用pyfit 1 Column Fixture 特点:行表格展现形式,一条测试用例对应一行数据 Wiki !define COMMA ...
- Unit Tests Tool - <What is “Mock You”> The introduction to moq #Reprinted#
From: http://www.cnblogs.com/wJiang/archive/2010/02/21/1670632.html Moq即Mock You Framework,故名思意是一个类似 ...
- java牛人给新人的几点建议
展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告 走过的路,回忆起来是那么曲折,把自己的一些心得体会分享给程序员兄弟姐妹们,虽然时代在变化,但是很可能你也会走我已经做过的1 ...
- Android 中文API (66) —— BluetoothClass.Device
前言 本章内容是android.bluetooth.BluetoothClass.Device,为Android蓝牙部分的章节翻译,版本为Android 2.3 r1,翻译来自中山大学的" ...
- LKD3
第三章 进程1. Unix操作系统的抽象:进程和文件2. 进程包括两个因素:可运行代码,和资源(打开的文件,挂起的信号,内核内部数据,处理器状态,地址空间)3. 线程是进程中活动的对象.4. 线程有独 ...
- css精灵(css script 技术)
上班差不多有15天了,感觉每天都有写不完的也页面,每天都有不同的东西需要学习进步,很充实哦.今天接触到css精灵这个东西.其实之前有看过这种技术,但是没有操作过,只是听说这个技术很强大,能干嘛干嘛,但 ...
- Android中的一些基础知识(二)
这几天在回顾Android的基础知识,就把一些常见的知识点整理一下,以后忘了也可以翻出来看一看. 简单介绍一下Activity的生命周期 在API文档中对生命周期回调的函数描述的很详细,这里我只是翻译 ...
- 基于hash的文档判重——simhash
本文环境: python3.5 ubuntu 16.04 第三方库: jieba 文件寄于github: https://github.com/w392807287/angelo_tools.git ...