Android編程實(shí)現(xiàn)仿易信精美彈出框效果【附demo源碼下載】
本文實(shí)例講述了Android編程實(shí)現(xiàn)仿易信精美彈出框效果。分享給大家供大家參考,具體如下:
截圖:

動(dòng)畫效果介紹:
1.點(diǎn)擊ActionBar上“+”按鈕,菜單從上方彈出(帶反彈效果);
2.再次點(diǎn)擊“+”、點(diǎn)擊空白區(qū)域或者點(diǎn)擊返回鍵,菜單向上方收起;
3.點(diǎn)擊彈出框上的按鈕時(shí),該按鈕放大,其它按鈕縮小,菜單整體漸變退出。
主體代碼:
1.Activity.
/**
* 仿易信動(dòng)畫彈出框
*/
public class MainActivity extends ActionBarActivity {
//用于標(biāo)記頁面頂端位置
private View topView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
topView = findViewById(R.id.main_top);
}
private PopupWindow popupWindow;
private int line1DeltaY, line2DeltaY;
//仿易信更多彈出框
private void showPopup() {
if (popupWindow == null) {
View contentView = LayoutInflater.from(this).inflate(R.layout.yixin_pop_layout, null);
//點(diǎn)擊空白區(qū)域關(guān)閉
View blankView = contentView.findViewById(R.id.yixin_more_blank);
View blankView2 = contentView.findViewById(R.id.yixin_more_blank2);
initItems(contentView);
//測量高度
int line2Height = ViewUtils.getViewMeasuredHeight(itemViews[0]);
line1DeltaY = -getActionBarHeight() - 40;
line2DeltaY = line1DeltaY - line2Height;
blankView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismissPopup();
}
});
blankView2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismissPopup();
}
});
popupWindow = new PopupWindow(contentView, ScreenUtils.getScreenW(this), ScreenUtils.getScreenH(this));
//隨便設(shè)置一個(gè)drawable作為背景
popupWindow.setBackgroundDrawable(new ColorDrawable());
}
if (!popupWindow.isShowing()) {
popupWindow.showAsDropDown(topView, 0, 0);
for (int i = 0; i < itemViews.length; i++) {
if (i < 3) {
//第一行
itemViews[i].startAnimation(AnimationHelper.createPopupAnimIn(this, line1DeltaY));
} else {
//第二行
itemViews[i].startAnimation(AnimationHelper.createPopupAnimIn(this, line2DeltaY));
}
}
popupWindow.getContentView().startAnimation(AnimationHelper.createPopupBgFadeInAnim());
}
}
private void dismissPopup() {
if (popupWindow == null || !popupWindow.isShowing()) {
return;
}
ViewGroup contentView = (ViewGroup) popupWindow.getContentView();
contentView.startAnimation(AnimationHelper.createPopupBgFadeOutAnim(AnimationHelper.TIME_OUT));
for (int i = 0; i < itemViews.length; i++) {
if (i < 3) {
//第一行
itemViews[i].startAnimation(AnimationHelper.createPopupAnimOut(this, line1DeltaY));
} else {
//第二行
itemViews[i].startAnimation(AnimationHelper.createPopupAnimOut(this, line2DeltaY));
}
}
//動(dòng)畫結(jié)束時(shí)隱藏popupWindow
contentView.postDelayed(new Runnable() {
@Override
public void run() {
popupWindow.dismiss();
}
}, AnimationHelper.TIME_OUT + 10);
}
private View[] itemViews;
//初始化popupWindow上的按鈕
private void initItems(View parent) {
int[] viewIds = new int[]{R.id.yixin_more_item1, R.id.yixin_more_item2, R.id.yixin_more_item3,
R.id.yixin_more_item4, R.id.yixin_more_item5, R.id.yixin_more_item6};
itemViews = new View[viewIds.length];
int itemWidth = ScreenUtils.getScreenW(this) / 3;
OnClickImpl l = new OnClickImpl();
for (int i = 0; i < viewIds.length; i++) {
int id = viewIds[i];
itemViews[i] = parent.findViewById(id);
GridLayout.LayoutParams p = (GridLayout.LayoutParams) itemViews[i].getLayoutParams();
p.width = itemWidth;
itemViews[i].setLayoutParams(p);
itemViews[i].setOnClickListener(l);
}
}
private class OnClickImpl implements View.OnClickListener {
@Override
public void onClick(View v) {
final int viewId = v.getId();
//背景動(dòng)畫
popupWindow.getContentView().startAnimation(AnimationHelper.createPopupBgFadeOutAnim(AnimationHelper.TIME_OUT_CLICK));
//動(dòng)畫結(jié)束時(shí)隱藏popupWindow
v.postDelayed(new Runnable() {
@Override
public void run() {
popupWindow.dismiss();
//動(dòng)畫結(jié)束時(shí)響應(yīng)點(diǎn)擊事件
handleEvent(viewId);
}
}, AnimationHelper.TIME_OUT_CLICK + 10);
//按鈕動(dòng)畫
for (View item : itemViews) {
if (item.getId() == v.getId()) {
//點(diǎn)擊的按鈕,放大
item.startAnimation(AnimationHelper.createPopupItemBiggerAnim(MainActivity.this));
} else {
//其它按鈕,縮小
item.startAnimation(AnimationHelper.createPopupItemSmallerAnim(MainActivity.this));
}
}
}
}
//popupWindow上按鈕的點(diǎn)擊事件
private void handleEvent(int viewId) {
Toast.makeText(this, "點(diǎn)擊了按鈕:" + viewId, Toast.LENGTH_SHORT).show();
}
private int getActionBarHeight() {
return getSupportActionBar().getHeight();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_more) {
if (popupWindow == null || !popupWindow.isShowing()) {
showPopup();
} else {
dismissPopup();
}
return true;
}
return super.onOptionsItemSelected(item);
}
//點(diǎn)擊返回鍵時(shí),如果popupWindow是顯示狀態(tài),則關(guān)閉它
@Override
public void onBackPressed() {
if (popupWindow != null && popupWindow.isShowing()) {
dismissPopup();
return;
}
super.onBackPressed();
}
}
2.動(dòng)畫工具類。
/**
* AnimationHelper
*/
public class AnimationHelper {
/**
* 進(jìn)入動(dòng)畫的時(shí)間
*/
public static final int TIME_IN = 300;
/**
* 進(jìn)入動(dòng)畫之后的反彈動(dòng)畫時(shí)間
*/
public static final int TIME_IN_BACK = 100;
/**
* 退出動(dòng)畫的時(shí)間
*/
public static final int TIME_OUT = 300;
/**
* 點(diǎn)擊PopupWindow上菜單后退出動(dòng)畫的時(shí)間
*/
public static final int TIME_OUT_CLICK = 500;
/**
* PopupWindow上菜單進(jìn)入動(dòng)畫
*/
public static Animation createPopupAnimIn(Context context, int fromYDelta) {
AnimationSet animationSet = new AnimationSet(context, null);
// animationSet.setInterpolator(new BounceInterpolator()); //結(jié)束時(shí)彈跳
animationSet.setFillAfter(true);
//移動(dòng)
TranslateAnimation translateAnim = new TranslateAnimation(0, 0, fromYDelta, 20);
translateAnim.setDuration(TIME_IN);
animationSet.addAnimation(translateAnim);
//回彈效果
TranslateAnimation translateAnim2 = new TranslateAnimation(0, 0, 0, -20);
translateAnim2.setStartOffset(TIME_IN);
translateAnim2.setDuration(TIME_IN_BACK);
animationSet.addAnimation(translateAnim2);
return animationSet;
}
/**
* PopupWindow上菜單離開動(dòng)畫
*/
public static Animation createPopupAnimOut(Context context, int toYDelta) {
AnimationSet animationSet = new AnimationSet(context, null);
animationSet.setFillAfter(true);
TranslateAnimation translateAnim = new TranslateAnimation(0, 0, 0, toYDelta);
translateAnim.setDuration(TIME_OUT);
animationSet.addAnimation(translateAnim);
return animationSet;
}
/**
* PopupWindow背景進(jìn)入動(dòng)畫(透明度漸變)
*/
public static Animation createPopupBgFadeInAnim() {
AlphaAnimation anim = new AlphaAnimation(0, 1.0f);
anim.setDuration(TIME_IN);
anim.setFillAfter(true);
return anim;
}
/**
* PopupWindow背景離開動(dòng)畫(透明度漸變)
*/
public static Animation createPopupBgFadeOutAnim(int duration) {
AlphaAnimation anim = new AlphaAnimation(1.0f, 0);
anim.setDuration(duration);
anim.setFillAfter(true);
return anim;
}
/**
* PopupWindow按鈕點(diǎn)擊動(dòng)畫
*/
public static Animation createPopupItemBiggerAnim(Context context) {
AnimationSet animationSet = new AnimationSet(context, null);
animationSet.setFillAfter(true);
//放大(設(shè)置縮放的中心點(diǎn)為自己的中心)
ScaleAnimation scaleAnim = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnim.setDuration(TIME_OUT_CLICK);
animationSet.addAnimation(scaleAnim);
//漸變
AlphaAnimation alphaAnim = new AlphaAnimation(1.0f, 0);
alphaAnim.setInterpolator(new AccelerateInterpolator());
alphaAnim.setDuration(TIME_OUT_CLICK);
animationSet.addAnimation(alphaAnim);
return animationSet;
}
/**
* PopupWindow按鈕點(diǎn)擊時(shí)其它按鈕的動(dòng)畫
*/
public static Animation createPopupItemSmallerAnim(Context context) {
//放大(設(shè)置縮放的中心點(diǎn)為自己的中心)
ScaleAnimation scaleAnim = new ScaleAnimation(1.0f, 0, 1.0f, 0,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnim.setDuration(TIME_OUT_CLICK);
scaleAnim.setFillAfter(true);
return scaleAnim;
}
}
完整實(shí)例代碼點(diǎn)擊此處本站下載。
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android開發(fā)動(dòng)畫技巧匯總》、《Android編程之a(chǎn)ctivity操作技巧總結(jié)》、《Android視圖View技巧總結(jié)》、《Android布局layout技巧總結(jié)》、《Android開發(fā)入門與進(jìn)階教程》、《Android資源操作技巧匯總》及《Android控件用法總結(jié)》
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
- Android編程實(shí)現(xiàn)仿QQ發(fā)表說說,上傳照片及彈出框效果【附demo源碼下載】
- Android仿微信進(jìn)度彈出框的實(shí)現(xiàn)方法
- 微信瀏覽器彈出框滑動(dòng)時(shí)頁面跟著滑動(dòng)的實(shí)現(xiàn)代碼(兼容Android和IOS端)
- Android 仿微信朋友圈點(diǎn)贊和評(píng)論彈出框功能
- Android 多種簡單的彈出框樣式設(shè)置代碼
- 高仿IOS的Android彈出框
- Android中自定義PopupWindow實(shí)現(xiàn)彈出框并帶有動(dòng)畫效果
- Android使用Dialog風(fēng)格彈出框的Activity
- Android 自定義彈出框?qū)崿F(xiàn)代碼
- Android AndBase框架內(nèi)部封裝實(shí)現(xiàn)進(jìn)度框、Toast框、彈出框、確認(rèn)框(二)
- Android實(shí)現(xiàn)可輸入數(shù)據(jù)的彈出框
相關(guān)文章
Kotlin Channel處理多個(gè)數(shù)據(jù)組合的流
最近項(xiàng)目中對(duì) kotlin 的使用比較多。不得不說 kotlin 確實(shí)可以極大的提高 android 的開發(fā)效率,channel用于協(xié)程之間的通訊,使用send和receive往通道里寫入或者讀取數(shù)據(jù),2個(gè)方法為非阻塞掛起函數(shù),channel是熱流,不管有沒有訂閱者都會(huì)發(fā)送2022-11-11
jenkins 遠(yuǎn)程構(gòu)建Android的過程詳解
這篇文章主要介紹了jenkins 遠(yuǎn)程構(gòu)建Android的過程詳解的相關(guān)資料,需要的朋友可以參考下2016-09-09
淺談RecyclerView(完美替代ListView,GridView)
RecyclerView絕對(duì)是一款功能強(qiáng)大的控件,涵蓋了ListView,GridView,瀑布流等數(shù)據(jù)表現(xiàn)的形式。本文對(duì)其進(jìn)行系統(tǒng)介紹,有需要的朋友可以看下2016-12-12
Android開發(fā)應(yīng)用中Broadcast Receiver組件詳解
本篇文章主要介紹了Android開發(fā)應(yīng)用中Broadcast Receiver組件詳解,想要學(xué)習(xí)的同學(xué)可以了解一下。2016-11-11
Android自定義Button并設(shè)置不同背景圖片的方法
這篇文章主要介紹了Android自定義Button并設(shè)置不同背景圖片的方法,涉及Android自定義控件的功能實(shí)現(xiàn)與布局相關(guān)技巧,需要的朋友可以參考下2016-01-01
老生常談Android HapticFeedback(震動(dòng)反饋)
下面小編就為大家?guī)硪黄仙U凙ndroid HapticFeedback(震動(dòng)反饋)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-04-04
Android通過bin二進(jìn)制程序調(diào)用jar原理
最近在研究monkey測試,發(fā)現(xiàn)monkey測試的代碼都是JAVA編寫的,通過編譯生成jar包,而我們?cè)趫?zhí)行測試時(shí)直接執(zhí)行/system/bin/monkey這個(gè)二進(jìn)制程序的,那么它是如何能調(diào)起java程序的呢,本文小編給大家介紹了Android通過bin二進(jìn)制程序調(diào)用jar原理,需要的朋友可以參考下2023-10-10

