看到网上一个Demo里面弹出菜单的动画效果很好看,自己就利用工作空余时间也写了一下。具体实现如下:

1 自定义一个显示Icon的ImageView,主要用来判断该ImageView是否需要放在父布局底部水平中心位置

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * Created by crab on 14-9-26.
 */
public class BottomCenterImageView extends ImageView {
    private boolean mLayoutParentBottomCenter=false;
    public BottomCenterImageView(Context context) {
        super(context);
    }

public BottomCenterImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.getTheme().obtainStyledAttributes( attrs, R.styleable.HoriAnimationLayout,0, 0);
        mLayoutParentBottomCenter=a.getBoolean(R.styleable.HoriAnimationLayout_bottomCenter,false);
        a.recycle();
    }

public BottomCenterImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.HoriAnimationLayout,defStyle,0);
        mLayoutParentBottomCenter=a.getBoolean(R.styleable.HoriAnimationLayout_bottomCenter,false);
        a.recycle();
    }
    public boolean isLayoutParentBottomCenter(){
        return mLayoutParentBottomCenter;
    }
}

2 建立一个容纳要显示ImageView的容器类

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;

/**
 * Created by crab on 14-9-26.
 */
public class HoriAnimationLayout extends LinearLayout{
    private int mTwoLineHeight=0;
    private int mOnewLineHeight=0;
    //是否有一个view放在该布局的底部水平中间位置
    private boolean mHasChildLayoutBottom=false;
    public static final int STATE_OPEN=0;
    public static final int STATE_CLOSE=1;
    private static final long ANIMATION_DURATION=500L;
    private int mState=STATE_CLOSE;
    public HoriAnimationLayout(Context context) {
        super(context);
        init(context);
    }

@Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        BottomCenterImageView child=null;
        int count=getChildCount();
        for(int i=0;i<count;i++){
            child= (BottomCenterImageView) getChildAt(i);
            if(!child.isLayoutParentBottomCenter()){
                child.setVisibility(View.INVISIBLE);
            }else{
                child.setOnClickListener(new OnClickListener(){

@Override
                    public void onClick(View v) {
                        if(mState==STATE_CLOSE){
                            open();
                        }else{
                            close();
                        }
                    }
                });
            }
        }
    }

public HoriAnimationLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

public HoriAnimationLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }
    private void init(Context context){
        mOnewLineHeight=(int) getResources().getDimension(R.dimen.circle_icon_size);
        mTwoLineHeight=(int) getResources().getDimension(R.dimen.circle_anim_parent_height);
    }
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount=getChildCount();
        if(childCount==0){
            throw new RuntimeException("请添加一个或者更多CircleAnimationImageView");
        }
        int gapCount=childCount-1;
        int gap=0;
        int leftOffset=0;
        BottomCenterImageView child=null;
        if(mHasChildLayoutBottom){
            gapCount=gapCount-1;
        }
        if(gapCount<=0){
            if(gapCount==-1){
                //只有一个并且需要直接布局到底部
                child= (BottomCenterImageView) getChildAt(0);
                child.layout((r-l)/2-child.getMeasuredWidth()/2,getMeasuredHeight()-child.getMeasuredHeight(),(r-l)/2+child.getMeasuredWidth()/2,getMeasuredHeight());
                return;
            }else if(gapCount==0){
                gap=(r-l)/2-mOnewLineHeight/2;
            }
        }else{
            gap=(r-l-(gapCount+1)*mOnewLineHeight)/gapCount;
        }
        for(int i=0;i<childCount;i++){
            child= (BottomCenterImageView) getChildAt(i);
            boolean isLayoutBottomCenter=child.isLayoutParentBottomCenter();
            if(isLayoutBottomCenter){
                child.layout((r-l)/2-child.getMeasuredWidth()/2,getMeasuredHeight()-child.getMeasuredHeight(),(r-l)/2+child.getMeasuredWidth()/2,getMeasuredHeight());
            }else{
                child.layout(leftOffset,0,leftOffset+child.getMeasuredWidth(),child.getMeasuredHeight());
                leftOffset=leftOffset+child.getMeasuredWidth()+gap;
            }
        }

}

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width=MeasureSpec.getSize(widthMeasureSpec);
        int childCount=getChildCount();
        for(int i=0;i<childCount;i++){
            BottomCenterImageView child= (BottomCenterImageView) getChildAt(i);
            if(child.isLayoutParentBottomCenter()){
                mHasChildLayoutBottom=true;
            }
            int childMeasureSize=MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY,mOnewLineHeight);
            child.measure(childMeasureSize,childMeasureSize);
        }
        int height=0;
        if(mHasChildLayoutBottom){
            height=mTwoLineHeight;
        }else{
            height=mOnewLineHeight;
        }
        setMeasuredDimension(width, height);
    }
    private void open(){
        if(mState==STATE_OPEN){
            return;
        }
        mState=STATE_OPEN;
        float dstX=getMeasuredWidth()/2-mOnewLineHeight/2;
        float dstY=getMeasuredHeight()-mOnewLineHeight;
        int childCount=getChildCount();
        Animation[] animations=new Animation[childCount];
        for(int i=0;i<childCount;i++) {
            final BottomCenterImageView child = (BottomCenterImageView) getChildAt(i);
            if(!child.isLayoutParentBottomCenter()) {
                float fromX = dstX - child.getLeft();
                float fromY = dstY - child.getTop();
                float toX = 0;
                float toY = 0;
                TranslateAnimation translateAnimation = new TranslateAnimation(Animation.ABSOLUTE, fromX, Animation.ABSOLUTE, toX,
                        Animation.ABSOLUTE, fromY, Animation.ABSOLUTE, toY);
                translateAnimation.setDuration(ANIMATION_DURATION);
                translateAnimation.setAnimationListener(new VisbleStateAniamtionListener(child, true));
                animations[i] = translateAnimation;
            }else{
                RotateAnimation rotateAnimation=new RotateAnimation(180,360,child.getWidth()/2,child.getHeight()/2);
                rotateAnimation.setDuration(ANIMATION_DURATION);
                rotateAnimation.setFillAfter(true);
                animations[i]=rotateAnimation;
            }
        }
        for(int i=0;i<childCount;i++){
            final BottomCenterImageView child = (BottomCenterImageView) getChildAt(i);
            child.startAnimation(animations[i]);
        }
    }
    private void close(){
        if(mState==STATE_CLOSE){
            return;
        }
        mState=STATE_CLOSE;
        float dstX=getMeasuredWidth()/2-mOnewLineHeight/2;
        float dstY=getMeasuredHeight()-mOnewLineHeight;
        int childCount=getChildCount();
        Animation[] animations=new Animation[childCount];
        for(int i=0;i<childCount;i++) {
            final BottomCenterImageView child = (BottomCenterImageView) getChildAt(i);
            if(!child.isLayoutParentBottomCenter()) {
                float fromX = 0;
                float fromY = 0;
                float toX = dstX - child.getLeft();
                float toY = dstY - child.getTop();
                TranslateAnimation translateAnimation = new TranslateAnimation(Animation.ABSOLUTE, fromX, Animation.ABSOLUTE, toX,
                        Animation.ABSOLUTE, fromY, Animation.ABSOLUTE, toY);
                translateAnimation.setDuration(ANIMATION_DURATION);
                translateAnimation.setAnimationListener(new VisbleStateAniamtionListener(child, false));
                animations[i] = translateAnimation;
            }else{
                RotateAnimation rotateAnimation=new RotateAnimation(0,180,child.getWidth()/2,child.getHeight()/2);
                rotateAnimation.setDuration(ANIMATION_DURATION);
                rotateAnimation.setFillAfter(true);
                animations[i]=rotateAnimation;
            }
        }
        for(int i=0;i<childCount;i++){
            final BottomCenterImageView child = (BottomCenterImageView) getChildAt(i);
            child.startAnimation(animations[i]);
        }
    }
    private class VisbleStateAniamtionListener implements Animation.AnimationListener{
        private View mView;
        private boolean mVisible;
        public VisbleStateAniamtionListener(View view,boolean visible){
            mView=view;
            mVisible=visible;
        }
        @Override
        public void onAnimationStart(Animation animation) {
            if(mView.getVisibility()!=View.VISIBLE){
                mView.setVisibility(View.VISIBLE);
            }
        }

@Override
        public void onAnimationEnd(Animation animation) {
            if(mVisible){
                mView.setVisibility(View.VISIBLE);
            }else{
                mView.setVisibility(View.INVISIBLE);
            }
        }

@Override
        public void onAnimationRepeat(Animation animation) {

}
    }

}

3定义布局文件,用到的图片资源可以自己去网上下载,最好用园行图片

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:customApp="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:background="#FFCCCCCC"
    android:layout_height="match_parent">

<com.example.crab.mycameratest.HoriAnimationLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        >
        <com.example.crab.mycameratest.BottomCenterImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pg_thrid_facebook_click"
            />
        <com.example.crab.mycameratest.BottomCenterImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pg_thrid_kupan_click"
            />
        <com.example.crab.mycameratest.BottomCenterImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pg_thrid_sina_click"
            />
        <com.example.crab.mycameratest.BottomCenterImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pg_thrid_twitter_click"
            />
        <com.example.crab.mycameratest.BottomCenterImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pg_thrid_qq_click"
            />
        <com.example.crab.mycameratest.BottomCenterImageView
            android:id="@+id/animationTrigger"
            customApp:bottomCenter="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pg_thrid_qq_click"
            />
       </com.example.crab.mycameratest.HoriAnimationLayout>

</RelativeLayout>

4定义自己需要用到的一些自定义资源与样式

dimens.xml

<resources>
    <dimen name="circle_icon_size">40dp</dimen>
    <dimen name="circle_anim_parent_height">128dp</dimen>
</resources>

attrs.xml

<declare-styleable name="HoriAnimationLayout">
        <attr name="bottomCenter" format="boolean"/>
    </declare-styleable>

Android自定义弹出菜单+动画实现相关推荐

  1. android 上下收缩动画,Android 带有弹出收缩动画的扇形菜单实例

    最近试着做了个Android 带有弹出收缩动画的扇形菜单,留个笔记记录一下. 效果如下 public class MainActivity extends AppCompatActivity impl ...

  2. Kotlin 仿微信长按列表弹出菜单(动画)

    一.测试 实现: 二.项目: 仿微信长按列表弹出菜单代码,MainActivity.kt class MainActivity : AppCompatActivity(), AdapterView.O ...

  3. android popupmenu 动态添加,Android PopupMenu弹出菜单的实现

    Android PopupMenu弹出菜单的实现 (1)布局文件:用于弹出菜单的处罚button: xmlns:tools="http://schemas.android.com/tools ...

  4. android 自定义 popupwindow,Android自定义弹出窗口PopupWindow使用技巧

    PopupWindow是Android上自定义弹出窗口,使用起来很方便. PopupWindow的构造函数为 public PopupWindow(View contentView, int widt ...

  5. android自定义弹出对话框,使用FlyDialog实现自定义Android弹窗对话框

    前言 学习的时候要用到弹窗,但是又觉得i同自带的弹窗样式有点不太美观,搜索资料后发现了FlycoDialog这个开源库,效果很好,而且实现起来也比较方便. 先列举一些比较好看的效果: NormalLi ...

  6. Android Dialog弹出方式动画

    //自定义Dialogclass myDialog extends Dialog{private Window window = null;public myDialog(Context contex ...

  7. android自定义弹出框样式实现

    前言: 做项目时,感觉Android自带的弹出框样式比较丑,很多应用都是自己做的弹出框,这里也试着自己做了一个. 废话不说先上图片: 实现机制 1.先自定义一个弹出框的样式 2.自己实现CustomD ...

  8. android 加号弹出菜单,Android仿微信、qq点击右上角加号弹出操作框

    Android仿微信.qq点击右上角加号弹出操作框,先上图,类似于下图这种,点击加号,会弹出一个对话框,如下图: 微信: 自己实现: 接下来,我们来实现此功能: 其实,实现原理就是,点击"+ ...

  9. Android 关机弹出菜单

    特别推荐: 移动资讯--<<我是开发者>>个人专访 关于android远程登录源码解析 Android源码之热血足球+PPT讲解 在Android系统中,长按Power键默认会 ...

最新文章

  1. NETSTAT日常应用归档
  2. java 继承 重载_java – 使用继承的重载方法
  3. 台北到淡水版Firefox玩网页游戏黑屏
  4. DPM Server切换
  5. 1、LeetCode784 字母大小写全排列
  6. 并查集(图论) LA 3644 X-Plosives
  7. C++primer 第 3 章 字符串、向量和数组 3 . 4 迭代器介绍
  8. BZOJ2330:[SCOI2011]糖果(差分约束)
  9. ios打包时候提示三方文件库错误,整理下解决的思路
  10. stdafx.h 简介及作用
  11. Windows记事本编码反汇编分析
  12. linux下QT发布程序双击打不开解决方法
  13. 如何快速新建多个不同名称文件夹?
  14. 教你如何攻克Kotlin中泛型型变的难点(下篇)
  15. 激光 pm2.5传感器 攀藤科技 stm32 调试通过
  16. Android实现Line登录分享
  17. 默纳克系统服务器怎么查看历史故障,默纳克3000主板怎么看历史故障
  18. 安装软件时提示:Error 1324. The path My Documents contains a invalid character
  19. openwrt配置内核驱动_为斐讯K2P编译OpenWRT LEDE,并启用mtk闭源wifi驱动及H3C认证
  20. 将 Modbus 工业传感器与开源 IIoT 网关连接起来

热门文章

  1. Java多线程Demo
  2. 生活的感悟(13、14)
  3. UE4的自定义输入设备插件制作方法
  4. 类版本ActionScript简介
  5. 力扣 2611. 老鼠和奶酪 排序
  6. PHP 中setcookie,用PHP如何设置setcookie?
  7. jsp调整字体大小font_jsp中CSS如何设置字体大小、斜体及颜色
  8. 【银行ATM取款机系统】
  9. 手机相册里android照片的来源,为什么手机相册总是出现不知道哪里来的照片?...
  10. “吃鸡”游戏代理有搞头吗?