“千变万化”——神奇的Android图片规格调整器(dialog技术解析篇)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 上篇说道,构思这个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仅讲述了一小部分逻辑,不过对于用户而言确实重要。

相关文章
|
2月前
|
Java 开发工具 Android开发
Android与iOS开发环境搭建全解析####
本文深入探讨了Android与iOS两大移动操作系统的开发环境搭建流程,旨在为初学者及有一定基础的开发者提供详尽指南。我们将从开发工具的选择、环境配置到第一个简单应用的创建,一步步引导读者步入移动应用开发的殿堂。无论你是Android Studio的新手还是Xcode的探索者,本文都将为你扫清开发道路上的障碍,助你快速上手并享受跨平台移动开发的乐趣。 ####
|
3天前
|
人工智能 搜索推荐 API
Cobalt:开源的流媒体下载工具,支持解析和下载全平台的视频、音频和图片,支持多种视频质量和格式,自动提取视频字幕
cobalt 是一款开源的流媒体下载工具,支持全平台视频、音频和图片下载,提供纯净、简洁无广告的体验
74 9
Cobalt:开源的流媒体下载工具,支持解析和下载全平台的视频、音频和图片,支持多种视频质量和格式,自动提取视频字幕
|
1月前
|
存储 Linux API
深入探索Android系统架构:从内核到应用层的全面解析
本文旨在为读者提供一份详尽的Android系统架构分析,从底层的Linux内核到顶层的应用程序框架。我们将探讨Android系统的模块化设计、各层之间的交互机制以及它们如何共同协作以支持丰富多样的应用生态。通过本篇文章,开发者和爱好者可以更深入理解Android平台的工作原理,从而优化开发流程和提升应用性能。
|
1月前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
2月前
|
安全 搜索推荐 Android开发
揭秘安卓与iOS系统的差异:技术深度对比
【10月更文挑战第27天】 本文深入探讨了安卓(Android)与iOS两大移动操作系统的技术特点和用户体验差异。通过对比两者的系统架构、应用生态、用户界面、安全性等方面,揭示了为何这两种系统能够在市场中各占一席之地,并为用户提供不同的选择。文章旨在为读者提供一个全面的视角,理解两种系统的优势与局限,从而更好地根据自己的需求做出选择。
121 2
|
2月前
|
开发框架 Dart Android开发
安卓与iOS的跨平台开发:Flutter框架深度解析
在移动应用开发的海洋中,Flutter作为一艘灵活的帆船,正引领着开发者们驶向跨平台开发的新纪元。本文将揭开Flutter神秘的面纱,从其架构到核心特性,再到实际应用案例,我们将一同探索这个由谷歌打造的开源UI工具包如何让安卓与iOS应用开发变得更加高效而统一。你将看到,借助Flutter,打造精美、高性能的应用不再是难题,而是变成了一场创造性的旅程。
|
2月前
|
安全 Java Linux
深入解析Android系统架构及其对开发者的意义####
【10月更文挑战第21天】 本文旨在为读者揭开Android操作系统架构的神秘面纱,探讨其如何塑造现代移动应用开发格局。通过剖析Linux内核、硬件抽象层、运行时环境及应用程序框架等关键组件,揭示Android平台的强大功能与灵活性。文章强调了理解Android架构对于开发者优化应用性能、提升用户体验的重要性,并展望了未来技术趋势下Android的发展方向。 ####
50 0
|
2月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
28天前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
53 19
|
2月前
|
IDE Java 开发工具
移动应用与系统:探索Android开发之旅
在这篇文章中,我们将深入探讨Android开发的各个方面,从基础知识到高级技术。我们将通过代码示例和案例分析,帮助读者更好地理解和掌握Android开发。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧。让我们一起开启Android开发的旅程吧!

推荐镜像

更多