Android开发之裁切(拍照+相冊)图像并设置头像小结

先看效果:

              
                      

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="320" height="480" > 
          

再贴代码:

自己定义选择照片底部弹出对话框布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/pop_layout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="#312E3F"
        android:gravity="center_horizontal"
        android:orientation="vertical" >

        <Button
            android:id="@+id/takePhotoBtn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dip"
            android:layout_marginRight="10dip"
            android:layout_marginTop="10dp"
            android:background="@drawable/btn_bg_blue"
            android:padding="10dp"
            android:text="拍照"
            android:textColor="@color/colorwhite"
            android:textSize="18sp"
            android:textStyle="bold" />

        <Button
            android:id="@+id/pickPhotoBtn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dip"
            android:layout_marginRight="10dip"
            android:layout_marginTop="5dp"
            android:background="@drawable/btn_bg_blue"
            android:padding="10dp"
            android:text="从相冊选择"
            android:textColor="@color/colorwhite"
            android:textSize="18sp"
            android:textStyle="bold" />

        <Button
            android:id="@+id/cancelBtn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="15dip"
            android:layout_marginLeft="10dip"
            android:layout_marginRight="10dip"
            android:layout_marginTop="20dp"
            android:background="@android:color/white"
            android:padding="10dp"
            android:text="取消"
            android:textColor="#373447"
            android:textSize="18sp"
            android:textStyle="bold" />
    </LinearLayout>

</RelativeLayout>

设备连接界面NavigationView header部分布局:

<?

xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/nav_headerView"
    android:layout_width="match_parent"
    android:layout_height="@dimen/nav_header_height"
    android:background="@drawable/drawer_background"
    android:gravity="bottom"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <com.aiofm.eminem.aiofmbgp.views.controls.CircleImage
        android:id="@+id/imageView"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_centerHorizontal="true"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:src="@android:drawable/sym_def_app_icon" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:text="鲍光普"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="[email protected]" />

</LinearLayout>

文件操作工具类代码:

package com.aiofm.eminem.aiofmbgp.common;

/**
 * 文件工具类
 * Created by eminem on 2016/4/10
 */
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.os.Environment;

public class FileUtil {
    /**
     * 将Bitmap 图片保存到本地路径。并返回路径
     * @param c 上下文
     * @param fileName 文件名
     * @param bitmap 图片资源
     * @return
     * Added by Bao guangpu on 2016/4/10
     */
    public static String saveFile(Context c, String fileName, Bitmap bitmap) {
        return saveFile(c, "", fileName, bitmap);
    }

    /**
     * 保存位图文件
     * @param c 上下文
     * @param filePath 保存文件路径
     * @param fileName 文件名
     * @param bitmap 图片资源
     * @return
     * Added by Bao guangpu on 2016/4/10
     */
    public static String saveFile(Context c, String filePath, String fileName, Bitmap bitmap) {
        byte[] bytes = bitmapToBytes(bitmap);
        return saveFile(c, filePath, fileName, bytes);
    }

    /**
     * 将位图转换为字节数组
     * @param bm 图片资源
     * @return
     * Added by Bao guangpu on 2016/4/10
     */
    public static byte[] bitmapToBytes(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(CompressFormat.JPEG, 100, baos);
        return baos.toByteArray();
    }

    /**
     * 保存字节数组文件
     * @param c 上下文
     * @param filePath 保存文件路径
     * @param fileName 文件名
     * @param bytes 字节数组
     * @return
     * Added by Bao guangpu on 2016/4/10
     */
    public static String saveFile(Context c, String filePath, String fileName, byte[] bytes) {
        String fileFullName = "";
        FileOutputStream fos = null;
        String dateFolder = new SimpleDateFormat("yyyyMMdd", Locale.CHINA)
                .format(new Date());
        try {
            String suffix = "";
            if (filePath == null || filePath.trim().length() == 0) {
                filePath = Environment.getExternalStorageDirectory() + "/JiaXT/" + dateFolder + "/";
            }
            File file = new File(filePath);
            if (!file.exists()) {
                file.mkdirs();
            }
            File fullFile = new File(filePath, fileName + suffix);
            fileFullName = fullFile.getPath();
            fos = new FileOutputStream(new File(filePath, fileName + suffix));
            fos.write(bytes);
        } catch (Exception e) {
            fileFullName = "";
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    fileFullName = "";
                }
            }
        }
        return fileFullName;
    }
}

自己定义ImageView代码:

package com.aiofm.eminem.aiofmbgp.views.controls;

/**
 * 自己定义ImageView
 * Created by eminem on 2016/4/11.
 */
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

import com.aiofm.eminem.aiofmbgp.R;

public class CircleImage extends ImageView {

    private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;

    private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
    private static final int COLORDRAWABLE_DIMENSION = 1;

    private static final int DEFAULT_BORDER_WIDTH = 0;
    private static final int DEFAULT_BORDER_COLOR = Color.BLACK;

    private final RectF mDrawableRect = new RectF();
    private final RectF mBorderRect = new RectF();

    private final Matrix mShaderMatrix = new Matrix();
    private final Paint mBitmapPaint = new Paint();
    private final Paint mBorderPaint = new Paint();

    private int mBorderColor = DEFAULT_BORDER_COLOR;
    private int mBorderWidth = DEFAULT_BORDER_WIDTH;

    private Bitmap mBitmap;
    private BitmapShader mBitmapShader;
    private int mBitmapWidth;
    private int mBitmapHeight;

    private float mDrawableRadius;
    private float mBorderRadius;

    private boolean mReady;
    private boolean mSetupPending;

    public CircleImage(Context context) {
        super(context);
    }

    public CircleImage(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CircleImage(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        super.setScaleType(SCALE_TYPE);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);

        mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);
        mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR);

        a.recycle();

        mReady = true;

        if (mSetupPending) {
            setup();
            mSetupPending = false;
        }
    }

    @Override
    public ScaleType getScaleType() {
        return SCALE_TYPE;
    }

    @Override
    public void setScaleType(ScaleType scaleType) {
        if (scaleType != SCALE_TYPE) {
            throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (getDrawable() == null) {
            return;
        }

        canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        setup();
    }

    public int getBorderColor() {
        return mBorderColor;
    }

    public void setBorderColor(int borderColor) {
        if (borderColor == mBorderColor) {
            return;
        }

        mBorderColor = borderColor;
        mBorderPaint.setColor(mBorderColor);
        invalidate();
    }

    public int getBorderWidth() {
        return mBorderWidth;
    }

    public void setBorderWidth(int borderWidth) {
        if (borderWidth == mBorderWidth) {
            return;
        }

        mBorderWidth = borderWidth;
        setup();
    }

    @Override
    public void setImageBitmap(Bitmap bm) {
        super.setImageBitmap(bm);
        mBitmap = bm;
        setup();
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        super.setImageDrawable(drawable);
        mBitmap = getBitmapFromDrawable(drawable);
        setup();
    }

    @Override
    public void setImageResource(int resId) {
        super.setImageResource(resId);
        mBitmap = getBitmapFromDrawable(getDrawable());
        setup();
    }

    private Bitmap getBitmapFromDrawable(Drawable drawable) {
        if (drawable == null) {
            return null;
        }

        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        try {
            Bitmap bitmap;

            if (drawable instanceof ColorDrawable) {
                bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
            } else {
                bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
            }

            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
            return bitmap;
        } catch (OutOfMemoryError e) {
            return null;
        }
    }

    private void setup() {
        if (!mReady) {
            mSetupPending = true;
            return;
        }

        if (mBitmap == null) {
            return;
        }

        mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

        mBitmapPaint.setAntiAlias(true);
        mBitmapPaint.setShader(mBitmapShader);

        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setAntiAlias(true);
        mBorderPaint.setColor(mBorderColor);
        mBorderPaint.setStrokeWidth(mBorderWidth);

        mBitmapHeight = mBitmap.getHeight();
        mBitmapWidth = mBitmap.getWidth();

        mBorderRect.set(0, 0, getWidth(), getHeight());
        mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2);

        mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth);
        mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2);

        updateShaderMatrix();
        invalidate();
    }

    private void updateShaderMatrix() {
        float scale;
        float dx = 0;
        float dy = 0;

        mShaderMatrix.set(null);

        if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
            scale = mDrawableRect.height() / (float) mBitmapHeight;
            dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
        } else {
            scale = mDrawableRect.width() / (float) mBitmapWidth;
            dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
        }

        mShaderMatrix.setScale(scale, scale);
        mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth, (int) (dy + 0.5f) + mBorderWidth);

        mBitmapShader.setLocalMatrix(mShaderMatrix);
    }

}

自己定义选择照片底部弹出对话框代码:

package com.aiofm.eminem.aiofmbgp.views.controls;

/**
 * Created by eminem on 2016/4/11.
 */
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.PopupWindow;

import com.aiofm.eminem.aiofmbgp.R;

public class SelectPicPopupWindow extends PopupWindow {

    private Button takePhotoBtn, pickPhotoBtn, cancelBtn;
    private View mMenuView;

    @SuppressLint("InflateParams")
    public SelectPicPopupWindow(Context context, OnClickListener itemsOnClick) {
        super(context);
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mMenuView = inflater.inflate(R.layout.layout_dialog_pic, null);
        takePhotoBtn = (Button) mMenuView.findViewById(R.id.takePhotoBtn);
        pickPhotoBtn = (Button) mMenuView.findViewById(R.id.pickPhotoBtn);
        cancelBtn = (Button) mMenuView.findViewById(R.id.cancelBtn);
        cancelBtn.setOnClickListener(itemsOnClick);
        pickPhotoBtn.setOnClickListener(itemsOnClick);
        takePhotoBtn.setOnClickListener(itemsOnClick);

        this.setContentView(mMenuView);
        this.setWidth(LayoutParams.MATCH_PARENT);
        this.setHeight(LayoutParams.WRAP_CONTENT);
        this.setFocusable(true);
        this.setAnimationStyle(R.style.PopupAnimation);
        ColorDrawable dw = new ColorDrawable(0x80000000);
        this.setBackgroundDrawable(dw);
        mMenuView.setOnTouchListener(new OnTouchListener() {

            @Override
            @SuppressLint("ClickableViewAccessibility")
            public boolean onTouch(View v, MotionEvent event) {

                int height = mMenuView.findViewById(R.id.pop_layout).getTop();
                int y = (int) event.getY();
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    if (y < height) {
                        dismiss();
                    }
                }
                return true;
            }
        });

    }

}

设备连接界面部分相关代码:

NavigationView navigationView = (NavigationView) findViewById(R.id.nav_mainview);
        navigationView.setNavigationItemSelectedListener(this);
        View headerView = navigationView.getHeaderView(0);
        avatarImg = (CircleImage) headerView.findViewById(R.id.imageView);
        avatarImg.setOnClickListener(this);
 @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.imageView:
                menuWindow = new SelectPicPopupWindow(mContext, itemsOnClick);
                menuWindow.showAtLocation(findViewById(R.id.drawer_layout),
                        Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0);
                break;
        }
    }
private View.OnClickListener itemsOnClick = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            menuWindow.dismiss();
            switch (v.getId()) {
                case R.id.takePhotoBtn:
                    Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    takeIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                            Uri.fromFile(new File(Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME)));
                    startActivityForResult(takeIntent, REQUESTCODE_TAKE);
                    break;
                case R.id.pickPhotoBtn:
                    Intent pickIntent = new Intent(Intent.ACTION_PICK, null);
                    pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
                    startActivityForResult(pickIntent, REQUESTCODE_PICK);
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case REQUESTCODE_PICK:
                try {
                    startPhotoZoom(data.getData());
                } catch (NullPointerException e) {
                    e.printStackTrace();
                }
                break;
            case REQUESTCODE_TAKE:
                File temp = new File(Environment.getExternalStorageDirectory() + "/" + IMAGE_FILE_NAME);
                startPhotoZoom(Uri.fromFile(temp));
                break;
            case REQUESTCODE_CUTTING:
                if (data != null) {
                    setPicToView(data);
                }
                break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    public void startPhotoZoom(Uri uri) {
        Intent 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", 300);
        intent.putExtra("outputY", 300);
        intent.putExtra("return-data", true);
        startActivityForResult(intent, REQUESTCODE_CUTTING);
    }

    private void setPicToView(Intent picdata) {
        Bundle extras = picdata.getExtras();
        if (extras != null) {
            Bitmap photo = extras.getParcelable("data");
            Drawable drawable = new BitmapDrawable(null, photo);
            urlpath = FileUtil.saveFile(mContext, "temphead.jpg", photo);
            avatarImg.setImageDrawable(drawable);
        }
    }
时间: 2024-10-14 03:03:59

Android开发之裁切(拍照+相冊)图像并设置头像小结的相关文章

Android开发之裁切(拍照+相册)图像并设置头像小结

先看效果:                                                   再贴代码: 自定义选择照片底部弹出对话框布局: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width=&

Android开发之手机拍照功能的实现(源代码分享)

Android系统里调用手机拍照的功能有两种方法一种直接调用手机自带的相机另一种就是使用自己做的拍照应用.比如Camera360 一款于各操作系统都有的的功能强大的手机摄影软件:能拍摄出不同风格,不同特效的照片,同时具有云服务和互联网分享功能,全球用户已经超过2.5亿.现在专门的开发一款手机摄影软件肯定没多大意义,已经比不过这些前辈了,我们只需学会如何调用手机自带的摄像机完成拍照并把照片获取过来,为用户提供上传头像,发表图文微博,传送图片的功能即可.完成上述的功能十分的简单,甚至不需要在清单文件

android开发——camera类拍照指定图片大小

android拍照开发 android开发实现拍照功能主要有两种方法: 直接调用系统照相机API实现拍照,拍完后,图片会保存在相册中,返回保存照片的路径,从而获取图片. 自己写SurfaceView调用camera来实现拍照,该方法触发一个回调,参数中包含一个图片字节数组,从而获取图片. 问题 当我们自定义相机时,需求需要指定拍照图片大小,然而不同手机会默认返回不同分辨率照片.所以需要对camera进行参数设置.通过设置setPictureSize,代码: // 获得相机参数 Camera.Pa

iOS开发中訪问相冊摄像像头

源代码下载地址http://download.csdn.net/download/jingjingxujiayou/7270479 在AppDelegate.m文件里 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScree

android开发实践之1:安装部署环境设置

一.安装包 1.andorid studio: 2.Java sdk: 二.操作步骤 1.安装Java SDK: 2.安装android studio; 3.创建Helloword工程并运行:遇到问题: 三.问题及解决方案 3.1.HAXM 运行android sdk: Extras->HAXM勾选并安装 下载完成后,在sdk/extras/intall/ Hardware_Accelerated_Execution_Manager目录下,运行安装程序: 3.2 Virtualization T

Android开发技巧——大图裁剪

本篇内容是接上篇<Android开发技巧--定制仿微信图片裁剪控件> 的,先简单介绍对上篇所封装的裁剪控件的使用,再详细说明如何使用它进行大图裁剪,包括对旋转图片的裁剪. 裁剪控件的简单使用 XML代码 使用如普通控件一样,首先在布局文件里包含该控件: <com.githang.clipimage.ClipImageView xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+i

Android开发学习笔记之Activity属性设置

麦子学院android开发老师说Activity是Android组件中最基本也是最为常见用的四大组件之一,在android开发中运用极为广泛,作为android开发初学者需要熟练掌握,麦子学院android开发老师分享了Activity属性的常用设置. android:allowTaskReparenting 是否允许activity更换从属的任务,比如从短信息任务 切换到浏览器任务. android:alwaysRetainTaskState 是否保留状态不变, 比如切换回home, 再从新打

Android开发:最全面、最易懂的Android屏幕适配解决方案

前言 Android的屏幕适配一直以来都在折磨着我们Android开发者,本文将结合: Google的官方权威适配文档 郭霖:Android官方提供的支持不同屏幕大小的全部方法 Stormzhang:Android 屏幕适配 鸿洋:Android 屏幕适配方案 凯子:Android屏幕适配全攻略(最权威的官方适配指导) 自身的思考&实践 给你带来一种全新.全面而逻辑清晰的Android屏幕适配思路,只要你认真阅读,保证你能解决Android的屏幕适配问题! 目录 定义 使得某一元素在Androi

Android开发 - 掌握ConstraintLayout(九)分组(Group)

使用ConstraintLayout后我们的布局是没有层级关系的,各个View之间都是平级关系,但是如果根据某个业务条件来控制多个View的显示与否,我们需要分别对每个View进行控制,需要调用多次setVisibility().这样就显得非常不方便. 本文所介绍的Group就是解决这个问题的. Group就是一个分组,可以关联多个View,从而只需要对这个分组进行控制就可以实现这样的场景. 我们下面来介绍它的使用. 添加分组 首先,我们添加一个Group: 关联元素 然后将页面上的元素拖动到这