1.简述
如何自定义DialogFragment,请参考Android自定义弹窗:DialogFragment
DialogFragment是谷歌官方推荐的对话框,可以高度自定义,灵活方便,非常适合编写产品经理设计的任何UI。
2.需求
设计自定义检查版本更新对话框,并加入动画效果,如下图:
3.开发
3.1 布局
res/layout/xxx.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
<LinearLayout
android:id="@+id/center_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/shape_white_radius_6_bg"
android:layout_marginTop="65dp"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@mipmap/pic_bo_lang"
/>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="更新"
android:textStyle="bold"
android:textSize="16sp"
android:textColor="#404040"
android:layout_marginLeft="17dp"
android:layout_marginRight="17dp"
/>
<TextView
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1.更新内容"
android:textSize="14sp"
android:textColor="#666666"
android:layout_marginTop="8dp"
android:layout_marginBottom="25dp"
android:layout_marginLeft="17dp"
android:layout_marginRight="17dp"
/>
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_marginLeft="17dp"
android:layout_marginRight="17dp"
android:layout_marginBottom="25dp"
>
<TextView
android:visibility="gone"
android:id="@+id/btn_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:textSize="16sp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:background="@drawable/shape_gray_efefef_radius_12"
android:gravity="center"
android:textColor="#666666"
android:text=" 取消 "
/>
<TextView
android:id="@+id/btn_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:textSize="16sp"
android:background="@drawable/shape_btn_blue_radius_20"
android:gravity="center"
android:textColor="#fff"
android:text="立即更新"
/>
</LinearLayout>
</LinearLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launch_rochet"
android:maxHeight="65dp"
android:layout_marginTop="10dp"
/>
<View
android:id="@+id/un_use_line"
android:layout_width="1dp"
android:layout_height="45dp"
android:background="#F0EFF2"
android:layout_centerHorizontal="true"
android:layout_below="@id/center_layout"
/>
<ImageView
android:id="@+id/btn_close"
android:layout_width="50dp"
android:layout_height="50dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="0dp"
android:paddingBottom="20dp"
android:src="@mipmap/ic_close_black"
android:layout_centerHorizontal="true"
android:layout_below="@id/un_use_line"
/>
</RelativeLayout>
3.2 类编写
其他次要代码见文末
package com.cupster.versiondialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
public class VersionOperateDialog extends DialogFragment {
private ImageView mBtnClose;
private TextView mTitle;
private TextView mContent;
private TextView mBtnOk;
private TextView mBtnCancel;
private View mLine ;
OnClickListener mPositiveListener ;
OnClickListener mNegativeListener;
private Object mVersionBean;
public static VersionOperateDialog Build(String title,String content,boolean closeShow) {
VersionOperateDialog inputDialog = new VersionOperateDialog();
Bundle bundle = new Bundle();
bundle.putString("title" , title);
bundle.putString("content" , content);
bundle.putBoolean("closeShow" , closeShow);
inputDialog.setArguments(bundle);
return inputDialog;
}
View mView;
int mWidth, mHeight;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if (mView == null) {
mView = inflater.inflate(R.layout.dialog_version_operate, container, false);
}
setStyle(STYLE_NORMAL, R.style.InputDialogStyle);
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
return mView;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
mTitle = mView.findViewById(R.id.title);
mContent = mView.findViewById(R.id.content);
mLine = mView.findViewById(R.id.un_use_line);
mBtnOk= mView.findViewById(R.id.btn_ok);
mBtnOk.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mPositiveListener != null) {
mPositiveListener.onClick(v);
}
dismiss();
}
});
mBtnCancel= mView.findViewById(R.id.btn_cancel);
mBtnCancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mNegativeListener != null) {
mNegativeListener.onClick(v);
}
dismiss();
}
});
mBtnClose = mView.findViewById(R.id.btn_close);
mBtnClose.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mNegativeListener != null) {
mNegativeListener.onClick(v);
}
dismiss();
}
});
initData();
}
private void initData() {
if (getArguments() != null){
boolean closeShow = getArguments().getBoolean("closeShow");
if (!closeShow){
mLine.setVisibility(View.GONE);
mBtnCancel.setVisibility(View.GONE);
mBtnClose.setVisibility(View.GONE);
}
String title = getArguments().getString("title");
if (!TextUtils.isEmpty(title)){
mTitle.setText(title);
}
String content = getArguments().getString("content");
if (!TextUtils.isEmpty(content)){
mContent.setText(content);
}
}
}
@Override
public void onStart() {
super.onStart();
//在DialogFragment的onstart里面设置,可以将对话框外部的背景设为透明
// Window window = getDialog().getWindow();
// WindowManager.LayoutParams windowParams = window.getAttributes();
// windowParams.dimAmount = 0.0f;
// window.setAttributes(windowParams);
//======================= ↑ 有效 ================================
//======================= ↓ 有效 ================================
Window window = getDialog().getWindow();
window.setDimAmount(0.2f);//设置亮度
window.setGravity(Gravity.CENTER);
window.setWindowAnimations(R.style.CenterPopupAnimation);
//全占宽、适配高
// window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
//自定义比例
WindowManager.LayoutParams layoutParams = window.getAttributes();
// if (mWidth > 0 && mHeight > 0) {
// layoutParams.height = mHeight;
// layoutParams.width = mWidth;
// } else {
// layoutParams.height = deviceHeight(getContext()) ;
layoutParams.width = (int) (0.7*deviceWidth(getContext()) );
// }
window.setLayout(layoutParams.width, layoutParams.height);
window.setBackgroundDrawableResource(android.R.color.transparent);
}
public void setObj(Object obj){
mVersionBean = obj;
}
public Object getObj (){
return mVersionBean;
}
public void setCancelListener(OnClickListener listener) {
mNegativeListener = listener;
}
public void setOkListener(OnClickListener mPositiveListener) {
this.mPositiveListener = mPositiveListener;
}
/**
* 获取设备宽度(px)
*
* @param context
* @return
*/
public static int deviceWidth(Context context) {
return context.getResources().getDisplayMetrics().widthPixels;
}
/**
* 获取设备高度(px)
*
* @param context
* @return
*/
public static int deviceHeight(Context context) {
return context.getResources().getDisplayMetrics().heightPixels;
}
/**
* dp 转化为 px
*
* @param context
* @param dpValue
* @return
*/
public static int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* px 转化为 dp
*
* @param context
* @param pxValue
* @return
*/
public static int px2dp(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
}
3.3 使用
package com.cupster.versiondialog;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
VersionOperateDialog dialog = VersionOperateDialog.Build("更新内容", "1.更新首页;\n2.更新导航布局;\n3.修复问题", true);
dialog.show(getSupportFragmentManager(), "version");
dialog.setOkListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//下载安装包,更新APP
Toast.makeText(MainActivity.this ,"下载中...",Toast.LENGTH_SHORT).show();
}
});
}
});
}
}
3.4 动画
res/anim/xxx.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<scale
android:duration="200"
android:pivotX="50%p"
android:pivotY="50%p"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:toXScale="1.2"
android:toYScale="1.2"/>
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<scale
android:duration="200"
android:pivotX="0%p"
android:pivotY="0%p"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="0.0"
android:toYScale="0.0"/>
</set>
3.5其他次要代码
1.shape_btn_blue_radius_20.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="20dp"/>
<gradient android:startColor="#508EF9"
android:endColor="#5577fb"
android:angle="135"
/>
</shape>
shape_gray_efefef_radius_12.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="20dp"/>
<solid android:color="#efefef"/>
</shape>
shape_white_radius_6_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<solid android:color="#fff" />
<corners android:radius="10dp"/>
</shape>
res/values/styles.xml 新增style
<resources>
<style name="InputDialogStyle" parent="android:Theme.Holo.Light.Dialog">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@null</item>
</style>
<!-- 弹出窗体的动画 从中间浮出弹出 -->
<style name="CenterPopupAnimation" parent="@android:style/Animation">
<!-- 边框 -->
<item name="android:windowFrame">@null</item>
<!-- 设置dialog的背景 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 是否浮现在activity之上 -->
<item name="android:windowIsFloating">true</item>
<!-- 半透明 -->
<item name="android:windowIsTranslucent">false</item>
<!-- 无标题 -->
<item name="android:windowNoTitle">true</item>
<!-- 模糊 -->
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowEnterAnimation">@anim/popup_alpha_in</item>
<item name="android:windowExitAnimation">@anim/popup_alpha_out</item>
</style>
</resources>