前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android从屏幕底部弹出popupWindow

Android从屏幕底部弹出popupWindow

作者头像
程序员飞飞
发布2020-02-27 16:56:19
3.4K1
发布2020-02-27 16:56:19
举报
文章被收录于专栏:Android&Java技术Android&Java技术

Android从屏幕底部弹出popupWindow

先看一下效果,看看是不是你想要的效果,免得浪费大家的时间,有一点说明,由于我录制的 gif 是用的模拟器,所以没有屏幕变暗的效果和加速的弹起的效果,实际效果以真机测试为准。

image
image

如果是你要的效果就可以继续向下看了…

1.首先是布局文件

代码语言:javascript
复制
<?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:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="160dp"
        android:background="@drawable/popupwindow_shape"
        android:gravity="center"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tvTakePhoto"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:layout_marginTop="30dp"
            android:background="@color/white"
            android:gravity="center"
            android:padding="10dp"
            android:text="拍照"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/tvSelectPhoto"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@color/white"
            android:gravity="center"
            android:padding="10dp"
            android:text="选择相册"
            android:textSize="18sp" />
    </LinearLayout>

</LinearLayout>

2.代码部分

我此处用的是一个加速的平移动画,从屏幕底部弹出,然后将屏幕的亮度变暗,让popupwindow获取焦点,就可以实现了popupwindow从手机屏幕底部弹出的效果,代码中注释已经写的很清楚了,直接看代码即可

2.1设置触发popupwindow的点击事件

代码语言:javascript
复制
public void onClick(View view) {
        switch (view.getId()) {
            case R.id.rlIcon:
                // TODO 弹出popupwind选择拍照或者从相册选择
                changeIcon(view);
                lightoff();
                break;
}

2.2定义3个属性变量

代码语言:javascript
复制
	// 声明PopupWindow
    private PopupWindow popupWindow;
    // 声明PopupWindow对应的视图
    private View popupView;

    // 声明平移动画
    private TranslateAnimation animation;

2.3弹起popupWindow

代码语言:javascript
复制
    /**
     * 弹出popupWindow更改头像
     */
    private void changeIcon() {
        if (popupWindow == null) {
            popupView = View.inflate(this, R.layout.item_change_icon, null);
            // 参数2,3:指明popupwindow的宽度和高度
            popupWindow = new PopupWindow(popupView, WindowManager.LayoutParams.MATCH_PARENT,
                    WindowManager.LayoutParams.WRAP_CONTENT);

            popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
                @Override
                public void onDismiss() {
                    lighton();
                }
            });

            // 设置背景图片, 必须设置,不然动画没作用
            popupWindow.setBackgroundDrawable(new BitmapDrawable());
            popupWindow.setFocusable(true);

            // 设置点击popupwindow外屏幕其它地方消失
            popupWindow.setOutsideTouchable(true);

            // 平移动画相对于手机屏幕的底部开始,X轴不变,Y轴从1变0
            animation = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0,
                    Animation.RELATIVE_TO_PARENT, 1, Animation.RELATIVE_TO_PARENT, 0);
            animation.setInterpolator(new AccelerateInterpolator());
            animation.setDuration(200);

            popupView.findViewById(R.id.tvTakePhoto).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 打开系统拍照程
                    Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    startActivityForResult(camera, CAMERA);
                    popupWindow.dismiss();
                    lighton();
                }
            });
            popupView.findViewById(R.id.tvSelectPhoto).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 打开系统图库选择图片
                    Intent picture = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                    startActivityForResult(picture, PICTURE);
                    popupWindow.dismiss();
                    lighton();
                }
            });
        }

        // 在点击之后设置popupwindow的销毁
        if (popupWindow.isShowing()) {
            popupWindow.dismiss();
            lighton();
        }

        // 设置popupWindow的显示位置,此处是在手机屏幕底部且水平居中的位置
        popupWindow.showAtLocation(SettingActivity.this.findViewById(R.id.setting), Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
        popupView.startAnimation(animation);
    }

2.4设置手机屏幕亮度的2个方法

代码语言:javascript
复制
    /**
     * 设置手机屏幕亮度变暗
     */
    private void lightoff() {
        WindowManager.LayoutParams lp = getWindow().getAttributes();
        lp.alpha = 0.3f;
        getWindow().setAttributes(lp);
    }

    /**
     * 设置手机屏幕亮度显示正常
     */
    private void lighton() {
        WindowManager.LayoutParams lp = getWindow().getAttributes();
        lp.alpha = 1f;
        getWindow().setAttributes(lp);
    }

3.我做的是手机拍照和相册选择的功能,在此也附上拍照和选择相册的代码,希望能帮到大家

代码语言:javascript
复制
    //Bimap:对应图片在内存中的对象
    //掌握:存储--->内存:BitmapFactory.decodeFile(String filePath)
    //                  BitmapFactory.decodeStream(InputStream is)
    //     内存--->存储:bitmap.compress(Bitmap.CompressFormat.PNG,100,OutputStream os);
    // 带回调的启动新的acitivity之后的回调方法
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == CAMERA && resultCode == RESULT_OK && data != null) {

            // 拍照
            Bundle bundle = data.getExtras();
            // 获取相机返回的数据,并转换为图片格式
            Bitmap bitmap = (Bitmap) bundle.get("data");
            // bitmap圆形裁剪
            bitmap = BitmapUtils.zoom(bitmap, DensityUtil.dp2px(this, 62), DensityUtil.dp2px(this, 62));
            Bitmap circleBitmap = BitmapUtils.circleBitmap(bitmap);

            //TODO 将图片上传到服务器的
            ivIcon.setImageBitmap(circleBitmap);
            // 将图片保存在本地
            try {
                saveImage(circleBitmap);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        } else if (requestCode == PICTURE && resultCode == RESULT_OK && data != null) {
            //图库
            Uri selectedImage = data.getData();
            //这里返回的uri情况就有点多了
            //**:在4.4.2之前返回的uri是:content://media/external/images/media/3951或者file://....在4.4.2返回的是content://com.android.providers.media.documents/document/image:3951或者
            //总结:uri的组成,eg:content://com.example.project:200/folder/subfolder/etc
            //content:--->"scheme"
            //com.example.project:200-->"host":"port"--->"authority"[主机地址+端口(省略) =authority]
            //folder/subfolder/etc-->"path" 路径部分
            //android各个不同的系统版本,对于获取外部存储上的资源,返回的Uri对象都可能各不一样,所以要保证无论是哪个系统版本都能正确获取到图片资源的话
            //就需要针对各种情况进行一个处理了
            String pathResult = getPath(selectedImage);

            Bitmap decodeFile = BitmapFactory.decodeFile(pathResult);
            Bitmap zoomBitmap = BitmapUtils.zoom(decodeFile, DensityUtil.dp2px(this, 62), DensityUtil.dp2px(this, 62));
            // bitmap圆形裁剪p
            Bitmap circleImage = BitmapUtils.circleBitmap(zoomBitmap);
            // 真实项目当中,是需要上传到服务器的..这步我们就不做了。
            ivIcon.setImageBitmap(circleImage);
            try {
                // 保存图片到本地
                saveImage(circleImage);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    // 将修改后的图片保存在本地存储中:storage/sdcard/Android/data/应用包名/files/xxx.png
    private void saveImage(Bitmap bitmap) throws FileNotFoundException {

        String path = this.getCacheDir() + "/tx.png";
        Log.e("TAG", "path = " + path);
        try {
            FileOutputStream fos = new FileOutputStream(path);
            // bitmap压缩(压缩格式、质量、压缩文件保存的位置)
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

//        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
//
//            File externalFilesDir = this.getExternalFilesDir(null);
//            File file = new File(externalFilesDir, "icon.png");
//            // 将Bitmap持久化
//            circleBitmap.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(file));
//        }
    }

    // 根据系统相册选择的文件获取路径
    @SuppressLint("NewApi")
    private String getPath(Uri uri) {
        int sdkVersion = Build.VERSION.SDK_INT;
        // 高于4.4.2的版本
        if (sdkVersion >= 19) {
            Log.e("TAG", "uri auth: " + uri.getAuthority());
            if (isExternalStorageDocument(uri)) {
                String docId = DocumentsContract.getDocumentId(uri);
                String[] split = docId.split(":");
                String type = split[0];
                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            } else if (isDownloadsDocument(uri)) {
                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),
                        Long.valueOf(id));
                return getDataColumn(this, contentUri, null, null);
            } else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }
                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{split[1]};
                return getDataColumn(this, contentUri, selection, selectionArgs);
            } else if (isMedia(uri)) {
                String[] proj = {MediaStore.Images.Media.DATA};
                Cursor actualimagecursor = this.managedQuery(uri, proj, null, null, null);
                int actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                actualimagecursor.moveToFirst();
                return actualimagecursor.getString(actual_image_column_index);
            }
        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();
            return getDataColumn(this, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
        return null;
    }

    private String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {column};
        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }


    private boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    public static boolean isMedia(Uri uri) {
        return "media".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

4.BitmapUtils

代码语言:javascript
复制
/**
 * Created by xpf on 2017/03/25 :)
 * Function:Bitmap对象的处理类
 */
public class BitmapUtils {

    // 将矩形的Bitmap对象转换为圆形的Bitmap
    public static Bitmap circleBitmap(Bitmap source) {
        // 获取图片的宽度
        int width = source.getWidth();
        // 创建一个与source等宽的Bitmap对象(正方形)
        Bitmap bitmap = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888);
        // 创建等大小的画布canvas
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        // 绘制一个圆圈:将此圆圈理解为下层图片(背景)
        canvas.drawCircle(width / 2, width / 2, width / 2, paint);

        // 设置图片相交情况下的处理方式
        // setXfermode:设置当绘制的图像出现相交情况时候的处理方式的,它包含的常用模式有哪几种
        // PorterDuff.Mode.SRC_IN 取两层图像交集部门,只显示上层图像,注意这里是指取相交叉的部分,然后显示上层图像
        // PorterDuff.Mode.DST_IN 取两层图像交集部门,只显示下层图像
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        // source:理解为上层图片(前景)
        canvas.drawBitmap(source, 0, 0, paint);

        return bitmap;
    }

    // 图片的压缩
    public static Bitmap zoom(Bitmap source, float width, float height) { //参数2,3不能声明int
        Matrix matrix = new Matrix();
        Bitmap bitmap = null;
        try {
            float scaleX = width / source.getWidth();
            float scaleY = height / source.getHeight();
            matrix.postScale(scaleX, scaleY);
            bitmap = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return bitmap;
    }
}

欢迎大家批评指正,如果对你有帮助的话请给我小小的点个赞也算是对我的鼓励…

本文首发于我的微信公众号,更多干货文章,请扫描二维码订阅哦:

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-03-25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Android从屏幕底部弹出popupWindow
    • 1.首先是布局文件
      • 2.代码部分
        • 2.1设置触发popupwindow的点击事件
        • 2.2定义3个属性变量
        • 2.3弹起popupWindow
        • 2.4设置手机屏幕亮度的2个方法
      • 3.我做的是手机拍照和相册选择的功能,在此也附上拍照和选择相册的代码,希望能帮到大家
        • 4.BitmapUtils
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档