首先祝大家周末愉快!前几天发表了几个项目中常用的实例,读者反映不错,可以看出大家还是希望技术能够在项目得到实际的应用,那么这篇博客就来聊聊实现用户修改头像的功能。
现在的APP,无论是大型的APP还是小型的项目,都或多或少的跟修改头像相关联,这个功能可以说在哪儿都用的说,所以有必要掌握这门技术。
先说说这个功能所需要掌握的知识点:
1.对startActivityForResult()方法要有一定的掌握;
- 文件存储的掌握;
3.PopupWindow的使用。
如果对这些知识点都比较了解的话,那看这篇博客就毫无压力了。
我这里为了方便,单独写了一个PopupWindow,用于封装我们想要的功能和实现PopupWindow的显示。先看看代码:
public class MPoPuWindow extends PopupWindow implements OnClickListener {
public Context mContext;
private Type type;
public Activity mActivity;
private File file;
private Uri ImgUri;
private TextView mTakePhoto, mAlbumPhoto, mCancel;
public MPoPuWindow(Context context, Activity mActivity) {
initView(context);
this.mActivity = mActivity;
}
private void initView(Context mContext) {
this.mContext = mContext;
View v = LayoutInflater.from(mContext).inflate(R.layout.activity_popu,
null);
setContentView(v);
mTakePhoto = (TextView) v.findViewById(R.id.photo_take);
mAlbumPhoto = (TextView) v.findViewById(R.id.photo_album);
mCancel = (TextView) v.findViewById(R.id.photo_cancel);
mTakePhoto.setOnClickListener(this);
mAlbumPhoto.setOnClickListener(this);
mCancel.setOnClickListener(this);
// 设置SelectPicPopupWindow弹出窗体的宽
this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
// 设置SelectPicPopupWindow弹出窗体的高
this.setHeight(ScreenUtils.getScreenHeight(mContext));
// 设置SelectPicPopupWindow弹出窗体可点�?
this.setTouchable(true);
this.setFocusable(true);
this.setOutsideTouchable(true);
// 刷新状�?
this.update();
// 设置SelectPicPopupWindow弹出窗体动画效果
this.setAnimationStyle(R.style.popuwindow_from_bottom);
// 实例化一个ColorDrawable颜色为半透明
ColorDrawable dw = new ColorDrawable(0x50000000);
// 设置SelectPicPopupWindow弹出窗体的背景
this.setBackgroundDrawable(dw);
}
public void showPopupWindow(View parent) {
if (!this.isShowing()) {
this.showAtLocation(parent, Gravity.BOTTOM, 0, 0);
} else {
this.dismiss();
}
}
@Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.photo_take:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
file = new File(Environment.getExternalStorageDirectory(),
System.currentTimeMillis() + ".jpg");
ImgUri = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, ImgUri);
mActivity.startActivityForResult(intent, 1);
type = Type.CAMERA;
if (listener != null) {
listener.getType(type);
listener.getImgUri(ImgUri, file);
}
this.dismiss();
break;
case R.id.photo_album:
Intent intent2 = new Intent("android.intent.action.PICK");
intent2.setType("image/*");
mActivity.startActivityForResult(intent2, 2);
type = Type.PHONE;
if (listener != null) {
listener.getType(type);
}
this.dismiss();
break;
case R.id.photo_cancel:
this.dismiss();
break;
default:
break;
}
}
public void onPhoto(Uri uri, int outputX, int outputY) {
Intent intent = null;
intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", outputX);
intent.putExtra("outputY", outputY);
intent.putExtra("scale", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.putExtra("return-data", true);
intent.putExtra("circleCrop", true);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true); // no face detection
mActivity.startActivityForResult(intent, 3);
}
public interface onGetTypeClckListener {
void getType(Type type);
void getImgUri(Uri ImgUri, File file);
}
private onGetTypeClckListener listener;
public void setOnGetTypeClckListener(onGetTypeClckListener listener) {
this.listener = listener;
}
}
重点的内容我都加上了注释,所以就不再赘述,值得注意的是我这里为了能跟外面交互,我定义了一个接口,然后对外暴露出两个方法,传递我们选择图片的时候产生的file和类型。另外我这里还用到了样式:
<style name="popuwindow_from_bottom">
<item name="android:windowEnterAnimation">@anim/popu_show_from_bottom</item>
<item name="android:windowExitAnimation">@anim/popu_hiden_from_top</item>
</style>
anim文件下的popu_hiden_from_top.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:toXDelta="0"
android:fromXDelta="0"
android:duration="300"
android:fromYDelta="0"
android:toYDelta="100%"
/>
</set>
还有一个popu_show_from_bottom.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:toXDelta="0"
android:fromXDelta="0"
android:duration="300"
android:fromYDelta="100%"
android:toYDelta="0"
/>
</set>
这个样式主要是给popuwindow添加一个弹出的样式,使它更好看一些。接下来就看看Activity怎么写的:
public class MainActivity extends Activity {
private ImageView mIvThumb;
private File file;
private Uri ImgUri;
private Type type;
private MPoPuWindow puWindow;
public enum Type {
PHONE, CAMERA
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIvThumb=(ImageView) findViewById(R.id.btn_change);
mIvThumb.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
puWindow = new MPoPuWindow(MainActivity.this, MainActivity.this);
puWindow.showPopupWindow(findViewById(R.id.set_act_parent));
puWindow.setOnGetTypeClckListener(new onGetTypeClckListener() {
@Override
public void getType(Type type) {
MainActivity.this.type = type;
}
@Override
public void getImgUri(Uri ImgUri, File file) {
MainActivity.this.ImgUri = ImgUri;
MainActivity.this.file = file;
}
});
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
Log.e("requestCode", type + "");
if (requestCode == 1) {
if (ImgUri != null) {
puWindow.onPhoto(ImgUri, 300, 300);
}
} else if (requestCode == 2) {
if (data != null) {
Uri uri = data.getData();
puWindow.onPhoto(uri, 300, 300);
}
} else if (requestCode == 3) {
if (type == Type.PHONE) {
if (data != null) {
Bundle extras = data.getExtras();
Bitmap bitmap = (Bitmap) extras.get("data");
if (bitmap != null) {
mIvThumb.setImageBitmap(bitmap);
}
}
} else if (type == Type.CAMERA) {
mIvThumb.setImageBitmap(BitmapFactory.decodeFile(file.getPath()));
}
}
}
}
其他都好理解,重点看看onActivityResult()方法里面的内容,这里分别使用了三个判断语句,也就是说返回的时候有三种情况,从相机里面返回的、从相册里面返回的、从切图界面返回的,对应不同的返回进行不一样的操作。代码再popuwindow里面都封装好了。
最后看到用到的两个工具类,这两个工具类都是项目中常用到的,可以保存下来以后用
第一个:DensityUtils
import android.content.Context;
import android.util.TypedValue;
/**
* 常用单位转换的辅助类
*
*
*
*/
public class DensityUtils {
private DensityUtils() {
/* cannot be instantiated */
throw new UnsupportedOperationException("cannot be instantiated");
}
/**
* dp转px
*
* @param context
* @param val
* @return
*/
public static int dp2px(Context context, float dpVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, context.getResources().getDisplayMetrics());
}
/**
* sp转px
*
* @param context
* @param val
* @return
*/
public static int sp2px(Context context, float spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spVal, context.getResources().getDisplayMetrics());
}
/**
* px转dp
*
* @param context
* @param pxVal
* @return
*/
public static float px2dp(Context context, float pxVal) {
final float scale = context.getResources().getDisplayMetrics().density;
return (pxVal / scale);
}
/**
* px转sp
*
* @param fontScale
* @param pxVal
* @return
*/
public static float px2sp(Context context, float pxVal) {
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
}
}
第二个:ScreenUtils
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.WindowManager;
/**
* 获得屏幕相关的辅助类
*
*
*
*/
public class ScreenUtils
{
private ScreenUtils()
{
/* cannot be instantiated */
throw new UnsupportedOperationException("cannot be instantiated");
}
/**
* 获得屏幕宽度
*
* @param context
* @return
*/
public static int getScreenWidth(Context context)
{
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}
/**
* 获得屏幕高度
*
* @param context
* @return
*/
public static int getScreenHeight(Context context)
{
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.heightPixels;
}
/**
* 获得状态栏的高度
*
* @param context
* @return
*/
public static int getStatusHeight(Context context)
{
int statusHeight = -1;
try
{
Class<?> clazz = Class.forName("com.android.internal.R$dimen");
Object object = clazz.newInstance();
int height = Integer.parseInt(clazz.getField("status_bar_height")
.get(object).toString());
statusHeight = context.getResources().getDimensionPixelSize(height);
} catch (Exception e)
{
e.printStackTrace();
}
return statusHeight;
}
/**
* 获取当前屏幕截图,包含状态栏
*
* @param activity
* @return
*/
public static Bitmap snapShotWithStatusBar(Activity activity)
{
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bmp = view.getDrawingCache();
int width = getScreenWidth(activity);
int height = getScreenHeight(activity);
Bitmap bp = null;
bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
view.destroyDrawingCache();
return bp;
}
/**
* 获取当前屏幕截图,不包含状态栏
*
* @param activity
* @return
*/
public static Bitmap snapShotWithoutStatusBar(Activity activity)
{
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bmp = view.getDrawingCache();
Rect frame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
int width = getScreenWidth(activity);
int height = getScreenHeight(activity);
Bitmap bp = null;
bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
- statusBarHeight);
view.destroyDrawingCache();
return bp;
}
}
这些都写好了。这个功能也就可基本实现了。
作者:qq_25193681 发表于2016/8/20 18:17:15 原文链接
阅读:43 评论:0 查看评论