持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情,希望大家多多支持,帮忙点个赞,谢谢!
前言
上篇说道,构思这个app时发现了很多平时未注意的问题,其中以Dialog弹窗为第一拦路虎,一方面是自己的技术不够成熟,一方面是自己平时未多多深入阅读。
正篇
本文将对我的dialog代码进行分析,希望可以进一步理解这里面的机制,从而实现自己需要的dialog.
代码风暴
public class PopupDialogFragment extends DialogFragment {
public static final String ARG_LAYOUT = "arg_layout";
public static final String ARG_GRAVITY = "arg_gravity";
int mLayout;
int mGravity = Gravity.CENTER;
protected View mView;
public static DialogFragment newInstance(int layout, int gravity) {
PopupDialogFragment fragment = new PopupDialogFragment();
fragment.setArgs(layout, gravity);
return fragment;
}
public void setArgs(int layout, int gravity) {
Bundle bundle = new Bundle();
bundle.putInt(ARG_LAYOUT, layout);
bundle.putInt(ARG_GRAVITY, gravity);
setArguments(bundle);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
Bundle bundle = getArguments();
mLayout = bundle.getInt(ARG_LAYOUT, 0);
mGravity = bundle.getInt(ARG_GRAVITY, 0);
}
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = getActivity().getLayoutInflater();
mView = inflater.inflate(mLayout, null);
Dialog dialog = new Dialog(getActivity());
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(mView);
dialog.setCanceledOnTouchOutside(true);
Window window = dialog.getWindow();
if (window != null) {
window.setBackgroundDrawableResource(R.color.transparent);
WindowManager.LayoutParams wlp = window.getAttributes();
wlp.gravity = mGravity;
wlp.width = WindowManager.LayoutParams.MATCH_PARENT;
wlp.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(wlp);
}
return dialog;
}
}
首先,我先用从而构建了PopupDialogFragment类继承了 DialogFragment类,从而构建了PopupDialogFragment此类用于底部弹窗的显示父类,然后我需要一个点击后能出现选择相机和相册的弹窗,所以实现了DialogSelectImage这个具体类:
public class DialogSelectImage extends PopupDialogFragment {
private AppCompatTextView tvCamera, tvGallery, tvCancel;
private View.OnClickListener mOnCameraClickListener;
private View.OnClickListener mOnGalleryClickListener;
public DialogSelectImage setOnCameraClickListener(View.OnClickListener onCameraClickListener) {
mOnCameraClickListener = onCameraClickListener;
return this;
}
public DialogSelectImage setOnGalleryClickListener(View.OnClickListener onGalleryClickListener) {
mOnGalleryClickListener = onGalleryClickListener;
return this;
}
public static DialogSelectImage newInstance() {
DialogSelectImage fragment = new DialogSelectImage();
fragment.setArgs(R.layout.layout_page_dialog_select_image, Gravity.BOTTOM);
return fragment;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
tvCamera = mView.findViewById(R.id.tvCamera);
tvGallery = mView.findViewById(R.id.tvGallery);
tvCancel = mView.findViewById(R.id.tvCancel);
tvCamera.setOnClickListener(new ThrottleClickEventAbstract() {
@Override
public void onThrottleClick(View v) {
if (mOnCameraClickListener != null) {
mOnCameraClickListener.onClick(v);
}
dismiss();
}
});
tvGallery.setOnClickListener(new ThrottleClickEventAbstract() {
@Override
public void onThrottleClick(View v) {
if (mOnGalleryClickListener != null) {
mOnGalleryClickListener.onClick(v);
}
dismiss();
}
});
tvCancel.setOnClickListener(new ThrottleClickEventAbstract() {
@Override
public void onThrottleClick(View v) {
dismiss();
}
});
return dialog;
}
}
其中这个属性决定了在底部显示:fragment.setArgs(R.layout.layout_page_dialog_select_image, Gravity.BOTTOM);
而现在进入相机或相册需要权限允许,所以又设置了openCamera()方法,通过点击事件去跳转征求用户的权限允许:
if (!NetConnectUtil.checkHasValidNet(mFragmentActivity)) {
ToastUtil.show(mFragmentActivity, R.string.str_unable_conn_network);
return;
}
FragmentTransaction fragmentTransaction = mFragmentActivity.getSupportFragmentManager().beginTransaction();
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
DialogSelectImage.newInstance()
.setOnCameraClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openCamera();
}
})
.setOnGalleryClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openGallery();
}
}).show(fragmentTransaction, "selectAvatar");
goCamera方法实现了拍照后回调,从而获取相关地址,本处代码是外层逻辑,内部逻辑是创建文件去存手机拍照文件,但这里getBitmap方法已经丢弃,需要想新的方法去实现:
private void goCamera(){
final String path = BizFileUtil.getAccountImgPath(mFragmentActivity, userName) + System.currentTimeMillis() + ".jpg";
ComponentSysUtil.goCamera((ActivityBase) mFragmentActivity, path, new IOnActivityResult() {
@Override
public void onActivityResult(int requestCode, int resultCode, final Intent data) {
File file = new File(path);
if (!file.exists()) {
XLog.d("onActivityResult: file not exist" + file);
return;
}
Bitmap bitmap = null;
try {
XLog.d("get Camera bitmap ");
bitmap = MediaStore.Images.Media.getBitmap(mFragmentActivity.getContentResolver(), Uri.fromFile(new File(path)));
} catch (IOException e) {
XLog.e("onActivityResult: E");
e.printStackTrace();
}
if (bitmap == null) {
XLog.d("Camera bitmap: null ");
return;
}
}
});
}
这个地方获取图片的地址或者URI,而MediaStore.Images.Media.getBitmap方法容易导致OOM,所以还是推荐使用图片压缩后展示。
小结
本节讲述了相机权限获取和相关弹窗的逻辑代码,下一节将继续分析代码,讲述图片坐标变化的使用,通过坐标更好的缩放bitmap。至此,本APP仅讲述了一小部分逻辑,不过对于用户而言确实重要。