示例源码下载http://download.csdn.net/detail/han1202012/9115227

EasyDialog 简介 :

-- 作用 : 用于在界面进行一些介绍, 说明;

-- 效果图 :

一. EasyDialog 源码解析

1. 实现原理

实现原理 :

-- EasyDialog 效果 : 在点击后, 会从屏幕外飞入对话框, 飞入恰好能够正好处于特定 View 组件的上方 或者下方;

-- 本质 : 点击按钮弹出的对话框会填充整个屏幕, 背景设置成透明的, 然后会计算组件坐标, 记录坐标位置, 再在弹出的整个对话框中 绘制一个 带小三角对话框的布局, 并让其执行动画;

2. 动画效果总结

(1) 动画实现核心代码

对话框显示小时动画效果实现代码片段 :

	private AnimatorSet animatorSetForDialogShow;
	private AnimatorSet animatorSetForDialogDismiss;
	private List<Animator> objectAnimatorsForDialogShow;
	private List<Animator> objectAnimatorsForDialogDismiss;

	/**
	 * 对话框显示的动画
	 */
	private void onDialogShowing() {
		if (animatorSetForDialogShow != null
				&& objectAnimatorsForDialogShow != null
				&& objectAnimatorsForDialogShow.size() > 0) {
			animatorSetForDialogShow.playTogether(objectAnimatorsForDialogShow);
			animatorSetForDialogShow.start();
		}
	}

	/**
	 * 对话框消失的动画
	 */
	private void onDialogDismiss() {
		if (animatorSetForDialogDismiss.isRunning()) {
			return;
		}
		if (animatorSetForDialogDismiss != null
				&& objectAnimatorsForDialogDismiss != null
				&& objectAnimatorsForDialogDismiss.size() > 0) {
			animatorSetForDialogDismiss
					.playTogether(objectAnimatorsForDialogDismiss);
			animatorSetForDialogDismiss.start();
			animatorSetForDialogDismiss
					.addListener(new Animator.AnimatorListener() {
						@Override
						public void onAnimationStart(Animator animation) {

						}

						@Override
						public void onAnimationEnd(Animator animation) {
							dialog.dismiss();
						}

						@Override
						public void onAnimationCancel(Animator animation) {

						}

						@Override
						public void onAnimationRepeat(Animator animation) {

						}
					});
		} else {
			dialog.dismiss();
		}
	}

(2) AnimatorSet 简介

AnimationSet 与 AnimatorSet 区别 : AnimatorSet 功能较强;

-- AnimatorSet : 执行的是 Animator 动画, 主要是靠改变视图属性产生动画效果;

-- AnimationSet : 执行的是 Animation 动画, 主要是靠改变视图的外观实现动画效果;

Animator 简介 : Animator 也是一种动画, 可以由用户执行开始, 中断执行, 还可以设置动画执行监听器;

AnimatorSet 简介 :

-- 功能 : 按照特定顺序执行一个 Animator 动画集合, 动画可以一起执行, 先后执行, 延迟执行;

-- 添加动画 : 有两种方式向 AnimatorSet 中添加动画, 调用 playTogether() 或者 playSequentially() 可以一次性向其中添加一个 动画集合, 调用 AnimatorSet.Builder 中得 play() 方法, 可以一个一个地向其中添加动画;

3. 坐标计算时机

坐标计算 : 计算坐标时需要获取组件的宽 和 高, 下面的代码中可以获取宽高, 获取到宽高后, 其坐标自然就计算好了;

-- 获取屏幕宽高代码 : 在其中的 onGlobalLayout 方法中可以获取其宽高;

		/*
		 * 获取对话框的宽 高
		 * 不是真的获取对话框的宽高, 是在对话框被构建绘制到 布局中时
		 * 利用这个时机去设置对话框位置
		 */
		ViewTreeObserver viewTreeObserver = dialogView.getViewTreeObserver();
		viewTreeObserver
				.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
					@Override
					public void onGlobalLayout() {
						// 当View可以获取宽高的时候,设置view的位置
						relocation(location);
					}
				});

4. 屏幕填充设置

设置是否填充屏幕 :

	/**
	 * 设置是否填充屏幕,如果不填充就适应布局内容的宽度,显示内容的位置会尽量随着三角形的位置居中
	 */
	public EasyDialog setMatchParent(boolean matchParent) {
		ViewGroup.LayoutParams layoutParams = llContent.getLayoutParams();
		layoutParams.width = matchParent ? ViewGroup.LayoutParams.MATCH_PARENT
				: ViewGroup.LayoutParams.WRAP_CONTENT;
		llContent.setLayoutParams(layoutParams);
		return this;
	}

-- 填充屏幕样式 : 可以看到 填充全屏, 左右只留下了 margin;

-- 不填充屏幕样式 : 不会横向充满屏幕;

二. EasyDialog 主要源码

1. EasyDialog 包装类

package cn.org.octopus.easydialog;

import java.util.ArrayList;
import java.util.List;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.RotateDrawable;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

public class EasyDialog {

	/**
	 * 上下文对象
	 */
	private Context context;
	/**
	 * 内容在三角形上面
	 */
	public static final int GRAVITY_TOP = 0;
	/**
	 * 内容在三角形下面
	 */
	public static final int GRAVITY_BOTTOM = 1;
	/**
	 * 对话框本身
	 */
	private Dialog dialog;
	/**
	 * 坐标
	 */
	private int[] location;
	/**
	 * 提醒框位置
	 */
	private int gravity;
	/**
	 * 外面传递进来的View
	 */
	private View contentView;
	/**
	 * 三角形
	 */
	private ImageView ivTriangle;
	/**
	 * 用来放外面传递进来的View
	 */
	private LinearLayout llContent;
	/**
	 * 触摸外面,是否关闭对话框
	 */
	private boolean touchOutsideDismiss;
	/**
	 * 提示框所在的容器
	 */
	private RelativeLayout rlOutsideBackground;

	public EasyDialog(Context context) {
		initDialog(context);
	}

	/**
	 * 初始化
	 * @param context
	 */
	private void initDialog(final Context context) {
		this.context = context;
		/*
		 * 说明传入的对象是一个 Activity
		 * 获取 Activity 的布局加载器
		 */
		LayoutInflater layoutInflater = ((Activity) context)
				.getLayoutInflater();
		//要显示的对话框布局
		View dialogView = layoutInflater.inflate(R.layout.layout_dialog, null);
		/*
		 * 获取对话框的宽 高
		 * 不是真的获取对话框的宽高, 是在对话框被构建绘制到 布局中时
		 * 利用这个时机去设置对话框位置
		 */
		ViewTreeObserver viewTreeObserver = dialogView.getViewTreeObserver();
		viewTreeObserver
				.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
					@Override
					public void onGlobalLayout() {
						// 当View可以获取宽高的时候,设置view的位置
						relocation(location);
					}
				});
		//初始化对话框所在的容器
		rlOutsideBackground = (RelativeLayout) dialogView
				.findViewById(R.id.rlOutsideBackground);
		//为容器设置点击事件, 一旦点击, 就让对话框消失
		rlOutsideBackground.setOnTouchListener(new View.OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				//关闭对话框前提 标志位true, 对话框不为 null
				if (touchOutsideDismiss && dialog != null) {
					onDialogDismiss();
				}
				return false;
			}
		});

		//对话框上部 或者 下部的 小三角形
		ivTriangle = (ImageView) dialogView.findViewById(R.id.ivTriangle);
		//对话框的长条
		llContent = (LinearLayout) dialogView.findViewById(R.id.llContent);

		//创建对话框
		dialog = new Dialog(
				context,
				isFullScreen() ? android.R.style.Theme_Translucent_NoTitleBar_Fullscreen
						: android.R.style.Theme_Translucent_NoTitleBar);
		//设置对话框布局
		dialog.setContentView(dialogView);

		//对话框显示动画
		animatorSetForDialogShow = new AnimatorSet();
		//对话框消失动画
		animatorSetForDialogDismiss = new AnimatorSet();

		objectAnimatorsForDialogShow = new ArrayList<>();
		objectAnimatorsForDialogDismiss = new ArrayList<>();

		//初始化默认值
		initData();
	}

	/**
	 * 初始化默认值
	 */
	private void initData() {
		this.setLocation(new int[] { 0, 0 })		//设置默认位置
				.setGravity(GRAVITY_BOTTOM)			//设置三角形位置 (上 或者 下)
				.setTouchOutsideDismiss(true)		//设置是否可以点击对话框消失
				.setOutsideColor(Color.TRANSPARENT)	//设置对话框外部背景颜色
				.setBackgroundColor(Color.BLUE)		//设置对话框背景
				.setMatchParent(true)				//设置是否填充全屏
				.setMarginLeftAndRight(24, 24);		//设置左右margin
	}

	/**
	 * 设置提示框中要显示的内容
	 */
	public EasyDialog setLayout(View layout) {
		if (layout != null) {
			this.contentView = layout;
		}
		return this;
	}

	/**
	 * 设置提示框中要显示的内容的布局Id
	 */
	public EasyDialog setLayoutResourceId(int layoutResourceId) {
		View view = ((Activity) context).getLayoutInflater().inflate(
				layoutResourceId, null);
		setLayout(view);
		return this;
	}

	/**
	 * 设置三角形所在的位置
	 *
	 * @param location
	 * 			传入 x y 坐标
	 * @return
	 */
	public EasyDialog setLocation(int[] location) {
		this.location = location;
		return this;
	}

	/**
	 * 设置三角形位置
	 * -- x 坐标 : x坐标值为attachedView所在屏幕位置的中心
	 * -- y 坐标 : y坐标值依据当前的gravity,如果gravity是top,则为控件上方的y值,如果是bottom,则为控件的下方的y值
	 *
	 * @param attachedView
	 *            在哪个View显示提示信息
	 */
	public EasyDialog setLocationByAttachedView(View attachedView) {
		if (attachedView != null) {
			//为成员变量赋值
			this.attachedView = attachedView;
			//该数组存储三角形位置数据
			int[] attachedViewLocation = new int[2];
			// 获取 attachedView 的位置, 左上角位置
			attachedView.getLocationOnScreen(attachedViewLocation);
			//计算 x 坐标, 即 attachedView 的中间位置
			attachedViewLocation[0] = attachedViewLocation[0]
					+ attachedView.getWidth() / 2;

			//计算 y 坐标
			switch (gravity) {
			case GRAVITY_BOTTOM:
				//如果三角形在下, 即三角形位置是 attachedView 的下方
				attachedViewLocation[1] = attachedViewLocation[1]
						+ attachedView.getHeight();
				break;
			case GRAVITY_TOP:
				//如果三角形在上, 即三角形位置是 attachedView 的上方, 即默认值
				break;
			}
			//设置三角形位置
			setLocation(attachedViewLocation);
		}
		return this;
	}

	/**
	 * 对话框所依附的View
	 * */
	private View attachedView = null;

	/**
	 * 设置显示的内容在上方还是下方,如果设置错误,默认是在下方
	 */
	public EasyDialog setGravity(int gravity) {
		//如果设置的位置值 既不是上 也不是下, 默认为下
		if (gravity != GRAVITY_BOTTOM && gravity != GRAVITY_TOP) {
			gravity = GRAVITY_BOTTOM;
		}

		//设置到成员变量中
		this.gravity = gravity;

		//设置三角形的图片,
		switch (this.gravity) {
		case GRAVITY_BOTTOM:
			ivTriangle.setBackgroundResource(R.drawable.triangle_bottom);
			break;
		case GRAVITY_TOP:
			ivTriangle.setBackgroundResource(R.drawable.triangle_top);
			break;
		}

		//对话框 主题长条的 View
		llContent.setBackgroundResource(R.drawable.round_corner_bg);
		// 如果用户调用setGravity()之前就调用过setLocationByAttachedView,需要再调用一次setLocationByAttachedView
		if (attachedView != null) {
			this.setLocationByAttachedView(attachedView);
		}
		//设置对话框颜色
		this.setBackgroundColor(backgroundColor);
		return this;
	}

	/**
	 * 设置是否填充屏幕,如果不填充就适应布局内容的宽度,显示内容的位置会尽量随着三角形的位置居中
	 */
	public EasyDialog setMatchParent(boolean matchParent) {
		ViewGroup.LayoutParams layoutParams = llContent.getLayoutParams();
		layoutParams.width = matchParent ? ViewGroup.LayoutParams.MATCH_PARENT
				: ViewGroup.LayoutParams.WRAP_CONTENT;
		llContent.setLayoutParams(layoutParams);
		return this;
	}

	/**
	 * 距离屏幕左右的边距
	 * 设置对话框所在的整个容器的布局
	 */
	public EasyDialog setMarginLeftAndRight(int left, int right) {
		RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) llContent
				.getLayoutParams();
		layoutParams.setMargins(left, 0, right, 0);
		llContent.setLayoutParams(layoutParams);
		return this;
	}

	/**
	 * 设置触摸对话框外面,对话框是否消失
	 */
	public EasyDialog setTouchOutsideDismiss(boolean touchOutsideDismiss) {
		this.touchOutsideDismiss = touchOutsideDismiss;
		return this;
	}

	/**
	 * 设置提醒框外部区域的颜色
	 */
	public EasyDialog setOutsideColor(int color) {
		rlOutsideBackground.setBackgroundColor(color);
		return this;
	}

	private int backgroundColor;

	/**
	 * 设置对话框的颜色
	 * <p/>
	 * 三角形的图片是layer-list里面嵌套一个RotateDrawable,在设置颜色的时候需要特别处理
	 * http://stackoverflow.
	 * com/questions/24492000/set-color-of-triangle-on-run-time
	 * http://stackoverflow
	 * .com/questions/16636412/change-shape-solid-color-at-runtime
	 * -inside-drawable-xml-used-as-background
	 */
	public EasyDialog setBackgroundColor(int color) {
		backgroundColor = color;
		LayerDrawable drawableTriangle = (LayerDrawable) ivTriangle
				.getBackground();
		GradientDrawable shapeTriangle = (GradientDrawable) (((RotateDrawable) drawableTriangle
				.findDrawableByLayerId(R.id.shape_id)).getDrawable());
		if (shapeTriangle != null) {
			shapeTriangle.setColor(color);
		} else {
			Toast.makeText(context, "shape is null", Toast.LENGTH_SHORT).show();
		}
		GradientDrawable drawableRound = (GradientDrawable) llContent
				.getBackground();
		if (drawableRound != null) {
			drawableRound.setColor(color);
		}
		return this;
	}

	/**
	 * 显示提示框
	 *
	 * 这个对话框 整个填充全屏, 显示后, 执行里面的 小对话框 (小三角 和 提示框内容)
	 */
	public EasyDialog show() {
		if (dialog != null) {
			if (contentView == null) {
				throw new RuntimeException(
						"您是否未调用setLayout()或者setLayoutResourceId()方法来设置要显示的内容呢?");
			}
			//设置对话框显示的内容
			llContent.addView(contentView);
			//显示整个对话框
			dialog.show();
			//显示小对话框的动画
			onDialogShowing();
		}
		return this;
	}

	/**
	 * 显示对话框的View的parent,如果想自己写动画,可以获取这个实例来写动画
	 *
	 * */
	public View getTipViewInstance() {
		return rlOutsideBackground.findViewById(R.id.rlParentForAnimate);
	}

	/** 横向 */
	public static final int DIRECTION_X = 0;
	/** 纵向 */
	public static final int DIRECTION_Y = 1;

	/**
	 * 水平动画
	 *
	 * @param direction
	 *            动画的方向
	 * @param duration
	 *            动画执行的时间长度
	 * @param values
	 *            动画移动的位置
	 * */
	public EasyDialog setAnimationTranslationShow(int direction, int duration,
			float... values) {
		return setAnimationTranslation(true, direction, duration, values);
	}

	/**
	 * 水平动画
	 *
	 * @param direction
	 *            动画的方向
	 * @param duration
	 *            动画执行的时间长度
	 * @param values
	 *            动画移动的位置
	 * */
	public EasyDialog setAnimationTranslationDismiss(int direction,
			int duration, float... values) {
		return setAnimationTranslation(false, direction, duration, values);
	}

	private EasyDialog setAnimationTranslation(boolean isShow, int direction,
			int duration, float... values) {
		if (direction != DIRECTION_X && direction != DIRECTION_Y) {
			direction = DIRECTION_X;
		}
		String propertyName = "";
		switch (direction) {
		case DIRECTION_X:
			propertyName = "translationX";
			break;
		case DIRECTION_Y:
			propertyName = "translationY";
			break;
		}
		ObjectAnimator animator = ObjectAnimator.ofFloat(
				rlOutsideBackground.findViewById(R.id.rlParentForAnimate),
				propertyName, values).setDuration(duration);
		if (isShow) {
			objectAnimatorsForDialogShow.add(animator);
		} else {
			objectAnimatorsForDialogDismiss.add(animator);
		}
		return this;
	}

	/**
	 * 对话框出现时候的渐变动画
	 *
	 * @param duration
	 *            动画执行的时间长度
	 * @param values
	 *            动画移动的位置
	 * */
	public EasyDialog setAnimationAlphaShow(int duration, float... values) {
		return setAnimationAlpha(true, duration, values);
	}

	/**
	 * 对话框消失时候的渐变动画
	 *
	 * @param duration
	 *            动画执行的时间长度
	 * @param values
	 *            动画移动的位置
	 * */
	public EasyDialog setAnimationAlphaDismiss(int duration, float... values) {
		return setAnimationAlpha(false, duration, values);
	}

	private EasyDialog setAnimationAlpha(boolean isShow, int duration,
			float... values) {
		ObjectAnimator animator = ObjectAnimator.ofFloat(
				rlOutsideBackground.findViewById(R.id.rlParentForAnimate),
				"alpha", values).setDuration(duration);
		if (isShow) {
			objectAnimatorsForDialogShow.add(animator);
		} else {
			objectAnimatorsForDialogDismiss.add(animator);
		}
		return this;
	}

	private AnimatorSet animatorSetForDialogShow;
	private AnimatorSet animatorSetForDialogDismiss;
	private List<Animator> objectAnimatorsForDialogShow;
	private List<Animator> objectAnimatorsForDialogDismiss;

	/**
	 * 对话框显示的动画
	 */
	private void onDialogShowing() {
		if (animatorSetForDialogShow != null
				&& objectAnimatorsForDialogShow != null
				&& objectAnimatorsForDialogShow.size() > 0) {
			animatorSetForDialogShow.playTogether(objectAnimatorsForDialogShow);
			animatorSetForDialogShow.start();
		}
	}

	/**
	 * 对话框消失的动画
	 */
	private void onDialogDismiss() {
		if (animatorSetForDialogDismiss.isRunning()) {
			return;
		}
		if (animatorSetForDialogDismiss != null
				&& objectAnimatorsForDialogDismiss != null
				&& objectAnimatorsForDialogDismiss.size() > 0) {
			animatorSetForDialogDismiss
					.playTogether(objectAnimatorsForDialogDismiss);
			animatorSetForDialogDismiss.start();
			animatorSetForDialogDismiss
					.addListener(new Animator.AnimatorListener() {
						@Override
						public void onAnimationStart(Animator animation) {

						}

						@Override
						public void onAnimationEnd(Animator animation) {
							dialog.dismiss();
						}

						@Override
						public void onAnimationCancel(Animator animation) {

						}

						@Override
						public void onAnimationRepeat(Animator animation) {

						}
					});
		} else {
			dialog.dismiss();
		}
	}

	/**
	 * 关闭提示框
	 */
	public void dismiss() {
		if (dialog != null && dialog.isShowing()) {
			onDialogDismiss();
		}
	}

	/**
	 * 根据x,y,重新设置控件的位置
	 *
	 * 因为setX setY为0的时候,都是在状态栏以下的,所以app不是全屏的话,需要扣掉状态栏的高度
	 */
	private void relocation(int[] location) {
		ivTriangle.setX(location[0] - ivTriangle.getWidth() / 2);
		ivTriangle.setY(location[1] - ivTriangle.getHeight() / 2
				- (isFullScreen() ? 0.0f : getStatusBarHeight()));// 因为三角形是通过XML绘制出来的,可以到activity_tip_overlay.xml中把三角形的那个ImageView背景设置一下,就知道什么情况了。所以需要减掉一半的高度
		switch (gravity) {
		case GRAVITY_BOTTOM:
			llContent.setY(location[1] - ivTriangle.getHeight() / 2
					- (isFullScreen() ? 0.0f : getStatusBarHeight())
					+ ivTriangle.getHeight());
			break;
		case GRAVITY_TOP:
			llContent.setY(location[1] - llContent.getHeight()
					- (isFullScreen() ? 0.0f : getStatusBarHeight())
					- ivTriangle.getHeight() / 2);
			break;
		}
		// 显示内容的区域往三角形靠拢
		int triangleCenterX = (int) (ivTriangle.getX() + ivTriangle.getWidth() / 2);// 三角形的中心点
		int contentWidth = llContent.getWidth();
		int rightMargin = getScreenWidth() - triangleCenterX;// 三角形中心距离屏幕右边的距离
		int leftMargin = getScreenWidth() - rightMargin;// 三角形中心距离屏幕左边的距离
		RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) llContent
				.getLayoutParams();
		int availableLeftMargin = leftMargin - layoutParams.leftMargin;// 左边可用的距离
		int availableRightMargin = rightMargin - layoutParams.rightMargin;// 右边可用的距离
		int x = 0;
		if (contentWidth / 2 <= availableLeftMargin
				&& contentWidth / 2 <= availableRightMargin)// 左右两边有足够的距离
		{
			x = triangleCenterX - contentWidth / 2;
		} else {
			if (availableLeftMargin <= availableRightMargin)// 判断三角形在屏幕中心的左边
			{
				x = layoutParams.leftMargin;
			} else// 三角形在屏幕中心的右边
			{
				x = getScreenWidth()
						- (contentWidth + layoutParams.rightMargin);
			}
		}
		llContent.setX(x);
	}

	/**
	 * 获取屏幕的宽度
	 * */
	private int getScreenWidth() {
		DisplayMetrics metrics = context.getResources().getDisplayMetrics();
		return metrics.widthPixels;
	}

	/**
	 * 获取状态栏的高度
	 */
	private int getStatusBarHeight() {
		int result = 0;
		int resourceId = context.getResources().getIdentifier(
				"status_bar_height", "dimen", "android");
		if (resourceId > 0) {
			result = context.getResources().getDimensionPixelSize(resourceId);
		}
		return result;
	}

	/**
	 * 判断下当前要显示对话框的Activity是否是全屏
	 */
	public boolean isFullScreen() {
		int flg = ((Activity) context).getWindow().getAttributes().flags;
		boolean flag = false;
		if ((flg & 1024) == 1024) {
			flag = true;
		}
		return flag;
	}

	/**
	 * 设置是否可以按返回按钮取消
	 * */
	public EasyDialog setCancelable(boolean cancelable) {
		dialog.setCancelable(cancelable);
		return this;
	}
}

2. EasyDialog 调用

package cn.org.octopus.easydialog;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity implements View.OnClickListener
{
    private RelativeLayout rlBackground;
    private Button btnTopLeft;
    private Button btnTopRight;
    private Button btnMiddleTop;
    private Button btnMiddleBottom;
    private Button btnBottomLeft;
    private Button btnBottomRight;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iniComponent();
    }

    private void iniComponent()
    {
        rlBackground = (RelativeLayout)findViewById(R.id.rlBackground);
        btnTopLeft = (Button) findViewById(R.id.btnTopLeft);
        btnTopRight = (Button) findViewById(R.id.btnTopRight);
        btnMiddleTop = (Button) findViewById(R.id.btnMiddleTop);
        btnMiddleBottom = (Button) findViewById(R.id.btnMiddleBottom);
        btnBottomLeft = (Button) findViewById(R.id.btnBottomLeft);
        btnBottomRight = (Button) findViewById(R.id.btnBottomRight);

        btnTopLeft.setOnClickListener(this);
        btnTopRight.setOnClickListener(this);
        btnMiddleTop.setOnClickListener(this);
        btnMiddleBottom.setOnClickListener(this);
        btnBottomLeft.setOnClickListener(this);
        btnBottomRight.setOnClickListener(this);
        rlBackground.setOnTouchListener(new View.OnTouchListener()
        {
            @Override
            public boolean onTouch(View v, MotionEvent event)
            {
                int[] location = new int[2];
                location[0] = (int)event.getX();
                location[1] = (int)event.getY();
                location[1] = location[1] + getActionBarHeight() + getStatusBarHeight();
                Toast.makeText(MainActivity.this, "x:" + location[0] + " y:" + location[1], Toast.LENGTH_SHORT).show();
                new EasyDialog(MainActivity.this)
                        .setLayoutResourceId(R.layout.layout_tip_content_horizontal)
                        .setBackgroundColor(MainActivity.this.getResources().getColor(R.color.background_color_black))
                        .setLocation(location)
                        .setGravity(EasyDialog.GRAVITY_TOP)
                        .setTouchOutsideDismiss(true)
                        .setMatchParent(false)
                        .setMarginLeftAndRight(24, 24)
                        .setOutsideColor(MainActivity.this.getResources().getColor(R.color.outside_color_gray))
                        .show();

                return false;
            }
        });
    }

    @Override
    public void onClick(View v)
    {
        switch (v.getId())
        {
            case R.id.btnTopLeft:
                View view = this.getLayoutInflater().inflate(R.layout.layout_tip_content_horizontal, null);
                new EasyDialog(MainActivity.this)
                        .setLayout(view)
                        .setBackgroundColor(MainActivity.this.getResources().getColor(R.color.background_color_black))
                        .setLocationByAttachedView(btnTopLeft)
                        .setGravity(EasyDialog.GRAVITY_BOTTOM)
                        .setAnimationTranslationShow(EasyDialog.DIRECTION_X, 1000, -600, 100, -50, 50, 0)
                        .setAnimationAlphaShow(1000, 0.3f, 1.0f)
                        .setAnimationTranslationDismiss(EasyDialog.DIRECTION_X, 500, -50, 800)
                        .setAnimationAlphaDismiss(500, 1.0f, 0.0f)
                        .setTouchOutsideDismiss(true)
                        .setMatchParent(true)
                        .setMarginLeftAndRight(24, 24)
                        .setOutsideColor(MainActivity.this.getResources().getColor(R.color.outside_color_trans))
                        .show();
                break;

            case R.id.btnTopRight:
                new EasyDialog(MainActivity.this)
                        .setLayoutResourceId(R.layout.layout_tip_image_text)
                        .setGravity(EasyDialog.GRAVITY_BOTTOM)
                        .setBackgroundColor(MainActivity.this.getResources().getColor(R.color.background_color_black))
                        .setLocationByAttachedView(btnTopRight)
                        .setAnimationTranslationShow(EasyDialog.DIRECTION_X, 350, 400, 0)
                        .setAnimationTranslationDismiss(EasyDialog.DIRECTION_X, 350, 0, 400)
                        .setTouchOutsideDismiss(true)
                        .setMatchParent(false)
                        .setMarginLeftAndRight(24, 24)
                        .setOutsideColor(MainActivity.this.getResources().getColor(R.color.outside_color_trans))
                        .show();
                break;
            case R.id.btnMiddleTop:
                new EasyDialog(MainActivity.this)
                        .setLayoutResourceId(R.layout.layout_tip_content_horizontal)
                        .setBackgroundColor(MainActivity.this.getResources().getColor(R.color.background_color_blue))
                        .setLocationByAttachedView(btnMiddleTop)
                        .setAnimationTranslationShow(EasyDialog.DIRECTION_Y, 1000, -800, 100, -50, 50, 0)
                        .setAnimationTranslationDismiss(EasyDialog.DIRECTION_Y, 500, 0, -800)
                        .setGravity(EasyDialog.GRAVITY_TOP)
                        .setTouchOutsideDismiss(true)
                        .setMatchParent(false)
                        .setMarginLeftAndRight(24, 24)
                        .setOutsideColor(MainActivity.this.getResources().getColor(R.color.outside_color_pink))
                        .show();
                break;
            case R.id.btnMiddleBottom:
                new EasyDialog(MainActivity.this)
                        .setLayoutResourceId(R.layout.layout_tip_content_horizontal)
                        .setGravity(EasyDialog.GRAVITY_BOTTOM)
                        .setBackgroundColor(MainActivity.this.getResources().getColor(R.color.background_color_brown))
                        .setLocationByAttachedView(btnMiddleBottom)
                        .setAnimationTranslationShow(EasyDialog.DIRECTION_Y, 1000, 800, -100, -50, 50, 0)
                        .setAnimationTranslationDismiss(EasyDialog.DIRECTION_Y, 500, 0, 800)
                        .setAnimationAlphaShow(1000, 0.3f, 1.0f)
                        .setTouchOutsideDismiss(true)
                        .setMatchParent(true)
                        .setMarginLeftAndRight(24, 24)
                        .setOutsideColor(MainActivity.this.getResources().getColor(R.color.outside_color_gray))
                        .show();
                break;
            case R.id.btnBottomLeft:
                new EasyDialog(MainActivity.this)
                        .setLayoutResourceId(R.layout.layout_tip_text)
                        .setBackgroundColor(MainActivity.this.getResources().getColor(R.color.background_color_pink))
                        .setLocationByAttachedView(btnBottomLeft)
                        .setGravity(EasyDialog.GRAVITY_TOP)
                        .setAnimationAlphaShow(600, 0.0f, 1.0f)
                        .setAnimationAlphaDismiss(600, 1.0f, 0.0f)
                        .setTouchOutsideDismiss(true)
                        .setMatchParent(false)
                        .setMarginLeftAndRight(24, 24)
                        .setOutsideColor(MainActivity.this.getResources().getColor(R.color.outside_color_trans))
                        .show();
                break;
            case R.id.btnBottomRight:
                new EasyDialog(MainActivity.this)
                        .setLayoutResourceId(R.layout.layout_tip_image_text)
                        .setBackgroundColor(MainActivity.this.getResources().getColor(R.color.background_color_yellow))
                        .setLocationByAttachedView(btnBottomRight)
                        .setGravity(EasyDialog.GRAVITY_TOP)
                        .setAnimationTranslationShow(EasyDialog.DIRECTION_X, 300, 400, 0)
                        .setAnimationTranslationShow(EasyDialog.DIRECTION_Y, 300, 400, 0)
                        .setAnimationTranslationDismiss(EasyDialog.DIRECTION_X, 300, 0, 400)
                        .setAnimationTranslationDismiss(EasyDialog.DIRECTION_Y, 300, 0, 400)
                        .setTouchOutsideDismiss(true)
                        .setMatchParent(false)
                        .setMarginLeftAndRight(24, 24)
                        .setOutsideColor(MainActivity.this.getResources().getColor(R.color.outside_color_trans))
                        .show();
                break;
        }
    }

    private int getStatusBarHeight()
    {
        int result = 0;
        int resourceId = this.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0)
        {
            result = this.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

    private int getActionBarHeight()
    {
        return this.getSupportActionBar().getHeight();
    }
}

【Android应用开发】EasyDialog 源码解析的更多相关文章

  1. iOS开发SDWebImage源码解析之SDWebImageManager的注解

    最近看了两篇博客,写得很不错,关于SDWebImage源码解析之SDWebImageManager的注解: 1.http://www.jianshu.com/p/6ae6f99b6c4c 2.http ...

  2. 【Android】IntentService &amp; HandlerThread源码解析

    一.前言 在学习Service的时候,我们一定会知道IntentService:官方文档不止一次强调,Service本身是运行在主线程中的(详见:[Android]Service),而主线程中是不适合 ...

  3. Android Handler消息机制源码解析

    好记性不如烂笔头,今天来分析一下Handler的源码实现 Handler机制是Android系统的基础,是多线程之间切换的基础.下面我们分析一下Handler的源码实现. Handler消息机制有4个 ...

  4. nginx开发_ngx_http_script源码解析

    功能简介 nginx中有很多配置项支持以变量的形式存在,在运行时根据实时值进行处理.例如如下配置: location / { sub_filter '<a href="http://1 ...

  5. nginx开发_ngx_palloc源码解析

    功能简介 ngx_pool_t是nginx开发中最经常使用到的内存容器.对动态内存的封装,由框架进行创建与释放,模块开发过程中仅需要进行内存申请,不需要关注何时释放.常见的pool对象有: 1. ng ...

  6. iOS开发——GPUImage源码解析

    一.基本概念 GPUImage:一个开源的.基于openGL的图片或视频的处理框架,其本身内置了多达120多种常见的滤镜效果,并且支持照相机和摄像机的实时滤镜,并且能够自定义图像滤镜.同时也很方便在原 ...

  7. Android HandlerThread源码解析

    在上一章Handler源码解析文章中,我们知道App的主线程通过Handler机制完成了一个线程的消息循环.那么我们自己也可以新建一个线程,在线程里面创建一个Looper,完成消息循环,可以做一些定时 ...

  8. Android开发——AsyncTask的使用以及源码解析

    .AsyncTask使用介绍  转载请标明出处:http://blog.csdn.net/seu_calvin/article/details/52172248 AsyncTask封装了Thread和 ...

  9. Android 热修复Nuwa的原理及Gradle插件源码解析

    现在,热修复的具体实现方案开源的也有很多,原理也大同小异,本篇文章以Nuwa为例,深入剖析.  Nuwa的github地址 https://github.com/jasonross/Nuwa 以及用于 ...

随机推荐

  1. C#编程语言与面向对象——抽象基类与接口

    在一个类前加“abstract”关键字,此类就成为抽象类. 对应的,在一个方法前加“abstract”关键字,此方法就成为抽象方法. abstract class Fruit //抽象类 { publ ...

  2. NOIP1999邮票面值设计[搜索|DP]

    题目描述 给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+K≤40)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值MAX,使在1-MAX之间的每一个邮资值都能得到 ...

  3. git的安装以及遇到的问题

    git安装以及遇到的问题 之前没有学会如何在Ubuntu下使用git,国庆放假回来后,完成了git的安装,补回来了之前没有学会的东西. 以下是我安装的过程以及遇到问题.解决问题的过程. 这次安装git ...

  4. [水煮 ASP.NET Web API2 方法论](3-2)直接式路由/属性路由

    问题 怎么样可以使用更贴近资源(Controller,Action)的方式定义路由. 解决方案 可以使用属性路由直接在资源级别声明路由.只要简单的在 Action 上使用属性路由 RouteAttri ...

  5. Linux嵌入式系统与硬件平台的关系

    一. Linux嵌入式系统 操作系统是一种在计算机上运行的软件,它的主要任务是管理计算机上的系统资源,为用户提供使用计算机及其外部设备的接口.它存在的目的是为了管理所有硬件资源,并且提供应用软件一个合 ...

  6. Node.js缓冲模块Buffer

    前言 Javascript是为浏览器而设计的,能很好的处理unicode编码的字符串,但对于二进制或非unicode编码的数据就显得无能为力. Node.js继承Javascript的语言特性,同时又 ...

  7. 使用rsyslog+loganalzey收集日志显示客户端ip

    http://www.ituring.com.cn/article/128536 rsyslog localhost 转发 http://bigsec.net/one/tool/rsyslog.htm ...

  8. 八 Appium常用方法介绍

    由于appium是扩展了Webdriver协议,所以可以使用webdriver提供的方法,比如在处理webview页面,完全可以使用webdriver中的方法.当然在原生应用中,也可以使用. 1.元素 ...

  9. 任务驱动 搭建SSM开发环境

    本篇主要阐述(IntelliJ IDEA + Maven + Spring + Spring MVC + Mybatis)搭建 为什么想要搭建ssm? 近期正好自己有一个小的点子要实现,恰好这学期开了 ...

  10. range与enumerate的区别

    在迭代中enumerate比range更能灵活,一般情况下尽量用erumerate,下面举例说明: 先来看range的使用: city_list = ['beijing', 'shanghai', ' ...