最近找工作,所以闲余时间还是比较充足的,今晚刚好没有睡意,抽取了一个之前项目中自己写过的一个功能。更换头像,可以拍照,可以从相册选取照片,有裁剪功能。其中的一个坑是PopupWindow的显示位置以及是否全屏显示适配不同手机。
话不多少,先上效果。


因为这个效果展示时间比较长,所以分了两段录结果还是大了,把gif图片质量压缩了。
大致解释下,效果就是点击按钮弹出popupwindow,更换头像可选择拍照和相册选取,并且可以裁剪。退出程序保存的头像依然保留。

下来先看看一步一步实现
由于今天我的Android studio有点,所以这个demo我是用eclipse写的。效果都是一样的。
1.PopupWindow 首先是布局样式 activity_choose_picture.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_margin="10dp"android:background="@color/btn_bottom_tv_gray"android:orientation="vertical" ><Buttonandroid:id="@+id/button_take_photo"style="@style/txt_camera_pop_menu"android:layout_width="match_parent"android:layout_height="45dp"android:background="@drawable/pop_first_selector"android:text="@string/camera_pop_camera"android:textSize="18sp" /><Buttonandroid:id="@+id/button_choice_photo"style="@style/txt_camera_pop_menu"android:layout_width="match_parent"android:layout_height="45dp"android:background="@drawable/pop_last_selector"android:text="@string/camera_pop_album"android:textSize="18sp" /><Buttonandroid:id="@+id/button_choice_cancel"style="@style/txt_camera_pop_menu"android:layout_width="match_parent"android:layout_height="45dp"android:layout_marginTop="10dp"android:background="@drawable/pop_single_selector"android:text="@string/camera_pop_cancel"android:textSize="18sp" /></LinearLayout></RelativeLayout>

这个就是弹出popupwindow的布局
资源文件,style.xml这里我们要自定义样式

    <!-- Application theme. --><style name="AppTheme" parent="AppBaseTheme"><!-- All customizations that are NOT specific to a particular API-level can go here. --><item name="android:windowNoTitle">true</item></style><style name="PopupAnimation" parent="android:Animation"><item name="android:windowEnterAnimation">@anim/push_bottom_in</item><item name="android:windowExitAnimation">@anim/push_bottom_out</item></style><style name="txt_camera_pop_menu"><!-- PopupWindow左右弹出的效果 --><item name="android:textColor">@color/camera_pop_normal</item><item name="android:textSize">16sp</item><item name="android:paddingTop">10dp</item><item name="android:paddingBottom">10dp</item><item name="android:gravity">center</item></style>

还有两个动画xml文件 push_bottom_in.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑入式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" ><translate
        android:duration="1000"android:fromYDelta="100%p"android:toYDelta="0" /><alpha
        android:duration="1000"android:fromAlpha="0.0"android:toAlpha="1.0" /></set>

push_bottom_out.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑入式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" ><translate
        android:duration="1000"android:fromYDelta="0"android:toYDelta="50%p" /><alpha
        android:duration="1000"android:fromAlpha="1.0"android:toAlpha="0.0" /></set>

需要注意的是这两个文件是建在anim目录下的,否则不起作用。
下来主要看MainActivity中的代码,
代码我注释写的比较详细,就直接看吧

package com.feilong.popupwindow;import java.io.ByteArrayOutputStream;
import java.io.File;
import java.lang.reflect.Field;import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.PopupWindow.OnDismissListener;public class MainActivity extends Activity {private Button button;private ImageView mIvHead;//更换的图片private View mGoneView;// 参照物private PopupWindow mPopupWindow; // popwindowprivate View mpopview; // 弹出框的布局private Bitmap photo; // 保存头像的Bitmap对象private static final int RESULT_PICK_PHOTO_CAMERA = 1; // 退出private static int CAMERA_RESULT = 100; // 拍照 标识码private static int LOAD_IMAGE_RESULT = 200; // 相册 标识码@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);button = (Button) findViewById(R.id.button1);mGoneView = findViewById(R.id.gone_view);mIvHead = (ImageView) findViewById(R.id.image_head);photo = FileUtill.readerByteArrayToSD(); // 读取保存的图片if (photo != null) {mIvHead.setImageBitmap(photo);} else {mIvHead.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher));}button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View view) {// TODO Auto-generated method stubshowPopupWindon();}});}/*** 弹出PopupWindow*/private void showPopupWindon() {int width = getResources().getDisplayMetrics().widthPixels;int height = getResources().getDisplayMetrics().heightPixels;// pxLayoutInflater inflater = LayoutInflater.from(this);mpopview = inflater.inflate(R.layout.activity_choose_picture, null);// 加载动画布局mPopupWindow = new PopupWindow(mpopview, width, height - dip2px(50)+ getStatusBarHeight());// 设置布局在屏幕中显示的位置,并且获取焦点// 设置PopupWindow的显示样式mPopupWindow.setAnimationStyle(R.style.PopupAnimation);// 实例化一个ColorDrawable颜色为半透明ColorDrawable dw = new ColorDrawable(0x00000000);// 设置SelectPicPopupWindow弹出窗体的背景mPopupWindow.setBackgroundDrawable(dw);backgroundAlpha(this, 0.5f);// 设置半透明0.0-1.0mPopupWindow.setFocusable(true);mPopupWindow.setOutsideTouchable(false);// 设置不允许在外点击消失// 设置当mPopupWindow取消时,界面恢复原来的颜色 不是可透明的mPopupWindow.setOnDismissListener(new OnDismissListener() {@Overridepublic void onDismiss() {// TODO Auto-generated method stubbackgroundAlpha(MainActivity.this, 1f);// 不透明}});mPopupWindow.showAsDropDown(mGoneView);// 弹出的mPopupWindow左上角正对mGoneView的左下角// 偏移量默认为0,0Button mTakePhotoBt = (Button) mpopview.findViewById(R.id.button_take_photo);// 拍照Button mChoicePhotoBt = (Button) mpopview.findViewById(R.id.button_choice_photo);// 相册选择Button mChoiceCancelBt = (Button) mpopview.findViewById(R.id.button_choice_cancel);// 取消// 拍照mTakePhotoBt.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mPopupWindow.dismiss();// destoryImage();File saveDirFile = new File(Environment.getExternalStorageDirectory(), "" + "temp.jpg");Intent intentCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 调用系统相机拍照intentCamera.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(saveDirFile));startActivityForResult(intentCamera, CAMERA_RESULT);}});// 从相册选择mChoicePhotoBt.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View view) {mPopupWindow.dismiss();// 取消弹窗// content://media/external/images/media 图片地址// Intent.ACTION_PICK 从图片中选择一张 并返回选择的图片Intent intentPhotoAlbum = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);startActivityForResult(intentPhotoAlbum, LOAD_IMAGE_RESULT);// 请求码200// 打开相册}});// 取消mChoiceCancelBt.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mPopupWindow.dismiss();}});}@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);// 拍照if (requestCode == CAMERA_RESULT && resultCode == RESULT_OK) {File temp = new File(Environment.getExternalStorageDirectory()+ "/" + "" + "temp.jpg");startPhotoZoom(Uri.fromFile(temp));}// 相册选择if (requestCode == LOAD_IMAGE_RESULT && data != null&& data.getData() != null) {// Uri selectedImage = data.getData();startPhotoZoom(data.getData());}// 取消if (requestCode == RESULT_PICK_PHOTO_CAMERA && data != null&& data.getExtras() != null) {Bundle extras = data.getExtras();Bitmap photo = extras.getParcelable("data");mIvHead.setImageBitmap(photo);ByteArrayOutputStream stream = new ByteArrayOutputStream();photo.compress(Bitmap.CompressFormat.JPEG, 60, stream);byte[] bytes = stream.toByteArray();mIvHead.setTag(bytes);String filePath = Environment.getExternalStorageDirectory() + "/"+ "" + "temp.jpg";FileUtill.writeByteArrayToSD(filePath, bytes, true);}}/*** 设置添加屏幕的背景透明度* * @param context* @param bgAlpha*            (透明度 取值返回0-1, 0全透明,1不透明)* @date 2016年8月6日*/public void backgroundAlpha(Activity context, float bgAlpha) {WindowManager.LayoutParams lp = context.getWindow().getAttributes();lp.alpha = bgAlpha;context.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);context.getWindow().setAttributes(lp);}/*** 根据手机的分辨率从 dp 的单位 转成为 px(像素)*/private int dip2px(float dpValue) {final float scale = getResources().getDisplayMetrics().density;return (int) (dpValue * scale + 0.5f);}/*** 裁剪图片方法实现*/@SuppressLint("NewApi")public void startPhotoZoom(Uri uri) {Intent intent = new Intent("com.android.camera.action.CROP");intent.setDataAndType(uri, "image/*");// 下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪intent.putExtra("crop", "true");// aspectX aspectY 是宽高的比例intent.putExtra("aspectX", 1);intent.putExtra("aspectY", 1); // outputX outputY 是裁剪图片宽高intent.putExtra("outputX", 200);intent.putExtra("outputY", 200);intent.putExtra("scale", true);// 黑边intent.putExtra("scaleUpIfNeeded", true);// 黑边intent.putExtra("return-data", true);startActivityForResult(intent, RESULT_PICK_PHOTO_CAMERA);}/*** 获取状态栏高速的方法* * @return* @date 2016年8月7日*/private int getStatusBarHeight() {Class<?> c = null;Object obj = null;Field field = null;int x = 0, sbar = 0;try {c = Class.forName("com.android.internal.R$dimen");obj = c.newInstance();field = c.getField("status_bar_height");x = Integer.parseInt(field.get(obj).toString());sbar = getResources().getDimensionPixelSize(x);} catch (Exception e1) {e1.printStackTrace();}return sbar;}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}}

这里有几点需要注意下,1,showAsDropDown(mGoneView);这个方法,是控制popupwindow显示位置的,参数我们可以理解为一个相对参照物,它是指// 弹出的PopupWindow左上角正对mGoneView的左下角显示。难怪之前没有设置的时候怎么调宽高都不是全屏显示的。这里的mGoneView是在activity_main.xml的最上面画一条线长宽为0,状态是gone。
2,mPopupWindow = new PopupWindow(mpopview, width, height - dip2px(50)
+ getStatusBarHeight());// 设置布局在屏幕中显示的位置,并且获取焦点
这行代码主要看第三个参数。其实测试发现Android系统有的PopupWindow计算高度的时候没有计算状态栏的高度,导致不能全屏。getStatusBarHeight()方法是获取状态栏高度的,至于这个为什么要减去dip2px(50)也不是很懂,他是一个把dp转化为px的一个方法。如果不减去则有的手机下面的“取消”会看不见。

photo = FileUtill.readerByteArrayToSD(); // 读取保存的图片if (photo != null) {mIvHead.setImageBitmap(photo);} else {mIvHead.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher));}

之前将照片保存在手机中,以后每当打开程序它会从sd卡中读取之前保存的头像照片,并且设置显示,如果没有的话,则默认显示ic_launcher。
今天时间有点晚了,就不在细说了,稍后我会附上

源码

,大家有兴趣可以下载

PopupWindow全屏显示以及适配不同手机屏幕之 应用实例 更换头像,拍照,相册选取附带动画效果相关推荐

  1. 表格全屏显示_2020-2026年中国手机显示屏市场现状研究分析与发展前景预测报告...

    2020-2026年中国手机显示屏市场现状研究分析与发展前景预测报告 报告编号:1295379 在线阅读:2020-2026年中国手机显示屏市场现状研究分析与发展前景预测报告_集成电路_中国市场调研在 ...

  2. andorid popwindow全屏显示时获取到的屏幕高度偏小

    有这样一个需求,使用popwindow来显示全屏,做一个屏保的功能. 之前使用下面代码来获取,但是发现真正给到popwindow去显示的时候,高度略低,非常丑陋. //获取屏幕宽度和高度Display ...

  3. 小米android9使用全屏,小米8应用怎么全屏显示 小米8应用全屏运行设置方法

    小米8怎么全屏显示应用?小米8应用怎么全屏显示?小米8手机采用的全面屏设计,显示屏比例是18.5:9,但是,最近很多小伙伴表示使用的应用都无法全屏显示,怎么回事呢?那是,因为你还没由设置允许应用全屏运 ...

  4. 计算机桌面怎么全屏显示,电脑显示器如何设置全屏 把电脑屏幕调成满屏的方法有哪些...

    今天给大家带来电脑显示器如何设置全屏,把电脑屏幕调成满屏的方法有哪些,让您轻松解决问题. 现在很多人都使用电脑玩游戏,为了让游戏效果达到最好,很多人都会购买比较好的显示器,设置电脑全屏进行玩耍,下面是 ...

  5. 计算机屏幕尺寸不是全屏,电脑屏幕有黑边撑不满怎么办_电脑屏幕不能全屏显示的解决方法...

    电脑屏幕有黑边撑不满怎么办?平时在使用电脑时候,如果是新手,可能会出现显示屏不能全屏显示的问题,有些情况是分辨率的问题,调整一下就好了,但有时候调整了也没有用,那么该怎么办呢?下面智能手机网小编来具体 ...

  6. 向日葵远程软件设置全屏显示的方法

    描述:向日葵远程软件设置全屏显示的方法 步骤: 屏幕顶部下箭头->缩放->自适应图像即可

  7. android华为手机全屏显示

    解决android华为提示全屏显示 最近发现很多应用在第一次安装之后,都会提示一个 [ 全屏显示] .一看,好像也没啥,但是对开发应用的开发者来说.感觉被打了一巴掌一样.自己好好编码完成的应用.出来个 ...

  8. h5 video 手机上无法显示_手机镜象投屏到电视上全屏显示

    手机镜象投屏到电视上全屏显示 随着手机投屏被越来越多的人知道,手机镜像投屏到大屏幕不是全屏的问题成为许多人心中的痛.AWIND奇机在2019年就做出了竖屏投屏器可以轻松让手机镜像投屏到大屏幕上为全屏显 ...

  9. android桌面壁纸显示不全屏显示,手机壁纸怎么全屏 全屏显示手机壁纸方法

    使用安卓手机的朋友都知道,安卓手机更换的壁纸是一个比较大的壁纸,对于一张背景壁纸图片我们手机界面看到的只有一部分,只有通过左右划屏才可以变换的看完整张桌面背面图片,那么如何在手机界面中看到一个完整的桌 ...

最新文章

  1. 6s如何无线连电脑连接服务器,iPhone 6s无线连接能力:WiFi与4G大提速
  2. sentry日志管理系统安装以及使用教程
  3. 一步一步搞定InfoPath(02)--配置VSTA
  4. 使用netsh命令来管理IP安全策略(详细介绍)
  5. WWDC 2018:iOS 12 通知的新特性
  6. mysql 数学函数
  7. 利用反射机制创建新类的两种方式及比较
  8. vmware 5.51 下安装Ubuntu Linux8.04安装vmware tools不成功
  9. JS file图片即选即得显示,前端交互图片即选即得
  10. linux密码过期不修改,Linux解决用户密码过期但不用修改密码的方法
  11. php自动载入类文件函数,我可以在没有PHP的类中自动加载函数文件吗?
  12. linux内存布局的内核实现--用户空间的映射方式
  13. makefile中的wildcard
  14. PCL之估计点云子集的表面法线
  15. Faster rcnn相关文章研究
  16. Tomcat各版本说明
  17. 方案展示 | 基于全志A40i的激光喷码机解决方案
  18. 奉子成婚,永远不可能成为潮流
  19. HTML5视频自动循环播放
  20. php最短路径tsp,最短路径tsp算法

热门文章

  1. 使用craco start后运行报错
  2. 抗倾覆机器人_抗倾覆稳定性,toppling stability,音标,读音,翻译,英文例句,英语词典...
  3. 前端基础——双单标签、行内块级元素、路径、常用标签
  4. 如果计算机黑屏请分析原因是什么原因,电脑系统黑屏死机故障原因分析处理
  5. 多重 for 循环优化,提升运行效率
  6. 投毒者对 PyPi 上的开源包开发者下手了
  7. [日推荐]『讯飞快读』人工智能高效管理时间
  8. (已解决)关于 WARNING: Ignoring invalid distribution -pencv-python .... 警告信息的处理方法
  9. 大牛推荐丨积分活动工具接口:积分商城api文档
  10. CMD打开闪退问题修复