Android动画+自定义Dialog实现闲鱼发布页面动态效果

时间:2022-05-16 12:09:10

先来看一下效果图:

Android动画+自定义Dialog实现闲鱼发布页面动态效果

一:新建一个项目DialogView

在layout文件夹下创建一个anmi的文件夹用于存放动画资源

1.首先创建进入Dialog和关闭Dialog时候的主题背景动画

进入Dialog时的动画 main_go_in.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="600">
<alpha
       android:fromAlpha="0"
       android:toAlpha="1.0"/>

</set>

alpha:透明度动画,改变视图整体透明度,透明度值由1~0,从可见到不可见的变化;

android:fromAlpha: 表示透明度的起始值,这里设置为0.0,表示完全透明,取值范围0~1;
android:toAlpha:表示透明度的结束值,这里设置为1.0,表示完全不透明,取值范围0~1;;
android:duration 表示动画持续的时间,这里设置为2000,单位是毫秒;

退出Dialog时的背景动画 main_go_out.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="400">
<alpha
       android:fromAlpha="1.0"
       android:toAlpha="0"/>
</set>

这里设置了背景色由不透明逐渐变成完全透明


2.创建旋转动画rotate用于上图底部退出按钮实现旋转效果

同理我们需要创建两个旋转动画一个用于进入Dialog一个用于关闭Dialog时的动画

首先创建进入时的旋转动画main_rotate_right.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="600"
    android:fromDegrees="-135"
    android:toDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    />

rotate动画

ps:toDegrees -fromDegrees > 0,则顺时针旋转;否则,逆时针旋转。

android:fromDegrees="-135"旋转开始的角度可以为负值

android:toDegrees="0"旋转结束的角度
android:pivotX="50%"
50%表示以当前View的左上角加上当前View宽高的50%做为初始点也就是view的中心点

android:pivotY="50旋转支点的xy轴坐标

退出Dialog时的rotate动画main_rotate_left.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"

    android:duration="400"
    android:fromDegrees="0"
    android:toDegrees="-135"
    android:pivotX="50%"
    android:pivotY="50%"
    />

实现了从右向左旋转

3.创建translate动画实现控件平移的效果

进入Dialog时的动画mian_shoot_in.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
           android:duration="600"
           android:fromYDelta="100%"
           android:interpolator="@android:anim/anticipate_overshoot_interpolator"
           android:toYDelta="0" />

 android:fromXDelta:平移开始X方向坐标(数值、百分数、百分数p,且多可以为正负)

 android:fromYDelta:平移开始Y方向坐标(数值、百分数、百分数p,且多可以为正负)

 android:toXDelta:平移结束X方向坐标(数值、百分数、百分数p,且多可以为正负)

 android:toYDelta:平移结束Y方向坐标(数值、百分数、百分数p,且多可以为正负)

这里实现了控件从下向上的平移效果

退出Dialog时的动画mian_shoot_out.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>

<translate xmlns:android="http://schemas.android.com/apk/res/android"
           android:duration="200"
           android:fromYDelta="0"
           android:interpolator="@android:anim/anticipate_interpolator"
           android:toYDelta="100%" />
实现了控件从上向下的平移效果

二,创建PublishDialog.java实现自定义Dialog

PublishDialog.java代码如下:
package com.example.dialogview;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

/**
 * Created by Dabin on 2017/5/11.
 */

public class PublishDialog extends Dialog {
    private RelativeLayout mPublishMainRlmian;
    private LinearLayout mPublishDialogFabu;
    private LinearLayout mPublishDialogHuishou;
    private LinearLayout mPublishDialogPinggu;
    private LinearLayout mPublishDialogLlBt;
    private ImageView mPublishDialogIvMenu;
    public static Dialog dialog;


    private Handler mHandler;
    private Context mContext;

    public PublishDialog(Context context) {
        this(context, R.style.main_publishdialog_style);
        //这里需要注意使用了一个自定义的Style代码会在下面给出

    }

    public PublishDialog(Context context, int themeResId) {
        super(context, themeResId);
        this.mContext=context;
        init();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //全屏
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.height = ViewGroup.LayoutParams.MATCH_PARENT;
        params.width = ViewGroup.LayoutParams.MATCH_PARENT;
        getWindow().setAttributes(params);
        dialog=this;

    }

    /**
     * 初始化
     */
    private void init() {
        setContentView(R.layout.mian_dialog_publish);
        mPublishMainRlmian = (RelativeLayout) findViewById(R.id.publish_main_rlmian);//主布局
        mPublishDialogFabu = (LinearLayout) findViewById(R.id.Publish_dialog_fabu);//发布
        mPublishDialogHuishou = (LinearLayout) findViewById(R.id.publish_dialog_huishou);//官方回收
        mPublishDialogPinggu = (LinearLayout) findViewById(R.id.publish_dialog_pinggu);//评估
        mPublishDialogLlBt = (LinearLayout) findViewById(R.id.publish_dialog_llBt);
        mPublishDialogIvMenu = (ImageView) findViewById(R.id.publish_dialog_ivMenu);//退出按钮x

        mHandler=new Handler();

        mPublishDialogLlBt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                outDia();
                //点击底部按钮区域退出dialog
            }
        });

        mPublishMainRlmian.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                outDia();
                //设置点击非控件区域也将退出dialog
            }
        });

    }

    @Override
    public void show() {
        super.show();
        goinDia();
    }
    /**
     * 进入dialog
     */
    private void goinDia() {
        mPublishDialogFabu.setVisibility(View.INVISIBLE);
        mPublishDialogHuishou.setVisibility(View.INVISIBLE);
        mPublishDialogPinggu.setVisibility(View.INVISIBLE);
        //首先把发布回收评估三个控件设置为不可见
        mPublishMainRlmian.setAnimation(AnimationUtils.loadAnimation(mContext,R.anim.main_go_in));
        //然后设置主布局的动画
        mPublishDialogIvMenu.setAnimation(AnimationUtils.loadAnimation(mContext,R.anim.main_rotate_right));
        //这里设置底部退出按钮的动画 这里是用了一个rotate动画
        mPublishDialogFabu.setVisibility(View.VISIBLE);
        //底部按钮动画执行过之后把发布设置为可见
        mPublishDialogFabu.setAnimation(AnimationUtils.loadAnimation(mContext,R.anim.mian_shoot_in));
        //然后让他执行mian_shoot_in动画这个动画里定义的是平移动画
        //在这里设置之后如果你同时设置其他两个评估和回收动画着这三个动画会同时从屏幕的底部向上平移
        //而我们想实现的效果是挨个向上平移这里 使用到了定时器handler开启一个线程定时100毫秒启动这个线程
        // 这样就可以达到挨个向上平移的效果
        // mHandler.postDelayed开启一个定时任务
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mPublishDialogHuishou.setVisibility(View.VISIBLE);
                mPublishDialogHuishou.setAnimation(AnimationUtils.loadAnimation(mContext,R.anim.mian_shoot_in));
            }
        },100);

        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mPublishDialogPinggu.setVisibility(View.VISIBLE);
                mPublishDialogPinggu.setAnimation(AnimationUtils.loadAnimation(mContext,R.anim.mian_shoot_in));


            }
        },200);
        //这里需要设置成两百不然会出现和评估同时向上滑动
    }

    /**
     * 退出Dialog
     */
    public void outDia(){
        mPublishMainRlmian.setAnimation(AnimationUtils.loadAnimation(mContext,R.anim.main_go_out));

        mPublishDialogIvMenu.setAnimation(AnimationUtils.loadAnimation(mContext,R.anim.main_rotate_left));
        //设置退出按钮从右向左旋转
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
               dismiss();
            }
        },500);
        //这里设置了一个定时500毫秒的定时器来执行dismiss();来关闭Dialog 我们需要在500毫秒的时间内完成对控件动画的设置
        mPublishDialogFabu.setAnimation(AnimationUtils.loadAnimation(mContext,R.anim.mian_shoot_out));
        //然后设置发布从上向下平移动画
        mPublishDialogFabu.setVisibility(View.INVISIBLE);
        //将其设置为不可见
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mPublishDialogHuishou.setAnimation(AnimationUtils.loadAnimation(mContext,R.anim.mian_shoot_out));
                mPublishDialogHuishou.setVisibility(View.INVISIBLE);
            }
        },100);
        //同理使用定时器将评估和回向下平移 这里需要注意的是评估和回收的定时器时间的设置不能大于关闭Dialog的定时时间
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mPublishDialogPinggu.setAnimation(AnimationUtils.loadAnimation(mContext,R.anim.mian_shoot_out));
                mPublishDialogPinggu.setVisibility(View.INVISIBLE);
            }
        },150);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if(isShowing()){
            outDia();
            //这里重写了onKeyDown方法捕获了back键的执行事件 点击back将退出Dialog
            return true;
        }else {
            return super.onKeyDown(keyCode, event);
        }

    }
//这三个方法设置了三个控件的点击事件并返回一个PublishDialog 这里需要一个OnClickListener的参数


    public PublishDialog setFabuClickListener(View.OnClickListener clickListener){
        mPublishDialogFabu.setOnClickListener(clickListener);
        return this;

    }
    public PublishDialog setHuishouClickListener(View.OnClickListener clickListener){
        mPublishDialogHuishou.setOnClickListener(clickListener);
        return this;

    }
    public PublishDialog setPingguClickListener(View.OnClickListener clickListener){
        mPublishDialogPinggu.setOnClickListener(clickListener);
        return this;

    }
这里代码不做过多的解释 注释写的很清楚每一步是干什么的 需要注意的是在
public PublishDialog(Context context) {
        this(context, R.style.main_publishdialog_style);
        //这里需要注意使用了一个自定义的Style代码会在下面给出

    }

方法中使用了一个自定义的Style代码如下:

<style name="main_publishdialog_style" parent="android:Theme.Holo.Light.Dialog">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:backgroundDimEnabled">false</item>
        <item name="android:windowAnimationStyle">@null</item>
    </style>

这里设置了Dialog的几个属性

最后是Dialog加载的布局文件mian_dialog_publish.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#da000000"
        android:clickable="true"
        android:id="@+id/publish_main_rlmian"
        >
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingBottom="80dp"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="26dp">
            <LinearLayout
                android:id="@+id/Publish_dialog_fabu"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:clickable="true"
                android:orientation="vertical"

                android:paddingTop="20dp" >

                <ImageView
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:layout_gravity="center_horizontal"
                    android:contentDescription="@null"
                    android:src="@mipmap/ic_fabushangpin" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:text="发布宝贝"
                    android:layout_marginTop="15dp"
                    android:textColor="#fff" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/publish_dialog_huishou"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:clickable="true"
                android:orientation="vertical"
                android:paddingTop="20dp" >

                <ImageView
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:layout_gravity="center_horizontal"
                    android:contentDescription="@null"
                    android:src="@mipmap/ic_huishou"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:text="官方回收"
                    android:layout_marginTop="15dp"
                    android:textColor="#fff" />
            </LinearLayout>
            <LinearLayout
                android:id="@+id/publish_dialog_pinggu"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:clickable="true"
                android:orientation="vertical"

                android:paddingTop="20dp" >

                <ImageView
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:layout_gravity="center_horizontal"
                    android:contentDescription="@null"
                    android:src="@mipmap/ic_pinggu"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:text="手机评估"
                    android:layout_marginTop="15dp"
                    android:textColor="#fff" />
            </LinearLayout>

        </LinearLayout>

        <ImageView
            android:id="@+id/publish_dialog_ivMenu"
            android:layout_width="wrap_content"
            android:layout_height="40dp"
            android:layout_gravity="bottom"
            android:contentDescription="@null"
            android:src="@mipmap/ic_mainpage_item"
            android:layout_marginBottom="14dp"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true" />
    </RelativeLayout>
    <LinearLayout
        android:id="@+id/publish_dialog_llBt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:gravity="bottom|center_horizontal"
        android:orientation="vertical"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="21dp">
    </LinearLayout>
</RelativeLayout>

三.修改acyivity_main.xml文件和MainActivity.java

1.activity_main.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.dialogview.MainActivity">

    <Button
        android:layout_marginTop="200dp"
        android:layout_marginLeft="130dp"
        android:id="@+id/dialogView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="打开Dialog"/>
</RelativeLayout>

在布局文件中加入了一个button按钮用于显示Dialog

MainActivity.java代码如下:

package com.example.dialogview;

import android.Manifest;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private Button dialogView;
    private PublishDialog publishDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dialogView = (Button) findViewById(R.id.dialogView);
        dialogView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (publishDialog==null){
                    publishDialog=new PublishDialog(MainActivity.this);
                    publishDialog.setFabuClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Toast.makeText(MainActivity.this, "发布", Toast.LENGTH_SHORT).show();
                        }
                    });
                    publishDialog.setHuishouClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Toast.makeText(MainActivity.this, "回收", Toast.LENGTH_SHORT).show();

                        }
                    });
                    publishDialog.setPingguClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Toast.makeText(MainActivity.this, "评估", Toast.LENGTH_SHORT).show();

                        }
                    });
                }
                publishDialog.show();
            }
        });
    }
}

这里获取了button按钮的实例并设置了点击事件 

再点击事件中实例化PublishDialog

并调用PublishDialog中的三个控件的点击事件方法

最后publishDialog.show();显示Dialog


主要的是对Android动画的运用

希望这篇文章对Android学习者有所帮助

源码地址:https://gitee.com/AndroidLMY/DialogView