之前一直觉得QQ换头像弹出的对话框挺好看的,而且在项目中也有这个
需求,于是写一个Demo出来分享一下。
话不多说,先来张效果图看看。
上面是QQ中的效果。
上面的效果图为需要实现的效果。
简单来说,就是弹出了一个对话框。接下来说说是怎么实现的。
对话框Dialog中的是自定义View,下面先贴出代码head_dialog。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"
android:orientation="vertical">
<TextView
android:id="@+id/tv_take_dy_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dialog_margin"
android:layout_marginRight="@dimen/dialog_margin"
android:background="@drawable/selector_top_round"
android:gravity="center"
android:padding="@dimen/dialog_padding"
android:text="@string/take_dy_photo"
android:textColor="@color/colorPrimary"
android:textSize="@dimen/text_size_16" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/cut_view_height"
android:layout_marginLeft="@dimen/dialog_margin"
android:layout_marginRight="@dimen/dialog_margin"
android:background="@color/grey" />
<TextView
android:id="@+id/tv_select_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dialog_margin"
android:layout_marginRight="@dimen/dialog_margin"
android:background="@drawable/selector_none_round"
android:gravity="center"
android:padding="@dimen/dialog_padding"
android:text="@string/select_photo"
android:textColor="@color/colorPrimary"
android:textSize="@dimen/text_size_16" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/cut_view_height"
android:layout_marginLeft="@dimen/dialog_margin"
android:layout_marginRight="@dimen/dialog_margin"
android:background="@color/grey" />
<TextView
android:id="@+id/tv_take_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dialog_margin"
android:layout_marginRight="@dimen/dialog_margin"
android:background="@drawable/selector_none_round"
android:gravity="center"
android:padding="@dimen/dialog_padding"
android:text="@string/take_photo"
android:textColor="@color/colorPrimary"
android:textSize="@dimen/text_size_16" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/cut_view_height"
android:layout_marginLeft="@dimen/dialog_margin"
android:layout_marginRight="@dimen/dialog_margin"
android:background="@color/grey" />
<TextView
android:id="@+id/tv_look_big_pic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dialog_margin"
android:layout_marginRight="@dimen/dialog_margin"
android:background="@drawable/selector_bottom_round"
android:gravity="center"
android:padding="@dimen/dialog_padding"
android:text="@string/look_big_pic"
android:textColor="@color/colorPrimary"
android:textSize="@dimen/text_size_16" />
<TextView
android:id="@+id/tv_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/dialog_margin"
android:background="@drawable/selector_all_round"
android:gravity="center"
android:padding="@dimen/dialog_padding"
android:text="@string/cancel"
android:textColor="@color/colorPrimary"
android:textSize="@dimen/text_size_16" />
</LinearLayout>
这里用的是TextView而没有用Button,是因为个人觉得点击Button的
时候出现的阴影出超出下方边缘,这样会影响视觉效果。
整个布局在底部,通过android:gravity=”bottom”来控制。
一共有5个按钮,共分为4种:
最顶上的一个TextView为上方2个圆角
中间2个位为矩形不带圆角
倒数第二个为下方2个圆角
最后一个为全到圆角
怎样画圆角?
下面给出其中一个TextView的样式top_round_normal.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="90"
android:endColor="@color/little_grey"
android:startColor="@color/little_grey" />
<!--设置圆角 上方圆角未点击-->
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="5dp"
android:topRightRadius="5dp" />
</shape>
在shape根标签中表明了是画rectangle矩形。gradient是指渐变色,这
里用的是同一种颜色。而corners标签下的四个属性顾名思义就是指定矩
形四个角的弧度的。
绘制完圆角后,发现TextView是有点击反馈效果的。自然而然想到了写
一个selector来区分点击的状态和正常状态,top_round_normal.xml是
正常状态,点击状态只需要更换一下gradient标签中的颜色即可。
给出其中一个selector代码:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/top_round_normal" android:state_focused="false" android:state_pressed="false" />
<item android:drawable="@drawable/top_round_pressed" android:state_focused="true" android:state_pressed="true" />
<item android:drawable="@drawable/top_round_pressed" android:state_focused="false" android:state_pressed="true" />
</selector>
然后通过background设置给TextView即可。
自定义Dialog视图完成,下面该说说怎么实现弹出Dialog了。
Dialog dialog = new Dialog(this, R.style.transparentFrameWindowStyle);
得到一个Dialog的实例,第二个参数为Dialog的样式。
<style name="transparentFrameWindowStyle" parent="android:style/Theme.Dialog">
<item name="android:windowBackground">@drawable/photo_choose_bg</item>
</style>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/trans" />
<!--四个圆角 未点击-->
<corners android:radius="20dp" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
</shape>
这里设置颜色为#00000000透明色,是为了将Dialog的背景色与
整个窗体颜色保持一致以达到是一个整体的效果。
Dialog dialog = new Dialog(this,
R.style.transparentFrameWindowStyle);
dialog.setContentView(view,
new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
然后将view设置给dialog显示出来并设置宽高。
在Dialog弹出是伴随着进来和出去两种动画效果。
在res目录下新建anim文件夹,新建2个资源文件。
dialog_anim_in.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromXDelta="0"
android:fromYDelta="1000"
android:toXDelta="0"
android:toYDelta="0" />
</set>
dialog_anim_out:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="1000" />
</set>
Window window = dialog.getWindow();
window.setWindowAnimations(R.style.anim_style);
WindowManager.LayoutParams layoutParams =
window.getAttributes();
layoutParams.x = 0;
layoutParams.y =
getWindowManager().getDefaultDisplay().getHeight();
//保证dialog窗体可以水平铺满
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
//设置dialog的摆放位置
dialog.onWindowAttributesChanged(layoutParams);
//设置点击dialog以为的区域dialog消失
dialog.setCanceledOnTouchOutside(true);
dialog.show();
获取到Dialog所在的窗体,然后通过window.setWindowAnimations()
方法设置动画。方法接收一个style。
style中正好有
android:windowEnterAnimation //进入动画
android:windowExitAnimation //退出动画
因此在style文件中定义好动画,然后设置给setWindowAnimations().
<style name="anim_style">
<item name="android:windowEnterAnimation">@anim/dialog_anim_in</item>
<item name="android:windowExitAnimation">@anim/dialog_anim_out</item>
</style>
最后设置宽高和摆放位置show出来。
最后需要提一点的是,由于这些按钮都是TextView,直接点击是
没有变色效果的,这是因为还没有给它们增加监听。
我们可以给它们设置一个空监听也可。
dialog.findViewById(R.id.tv_take_dy_photo).setOnClickListener(null);
由于个人水平有限,整个过程描述的比较零散,特此献上小Demo
完整Demo在这里