您的位置:首页 > 移动开发 > Android开发

Android BottomSheet:以选取图片为例(2)

2016-06-28 15:37 495 查看

Android BottomSheet:以选取图片为例(2)

附录文章5简单介绍了常见的分享面板在BottomSheet中的具体应用。本文再以常见的选取图片为例写一个例子。

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<com.flipboard.bottomsheet.BottomSheetLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/bottomsheet"
android:layout_width="match_parent"
android:layout_height="match_parent">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">

<Button
android:id="@+id/image_picker_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
android:layout_marginBottom="16dp"
android:text="选择"
/>

<ImageView
android:id="@+id/image_picker_selected"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:layout_below="@id/image_picker_button"
/>

</RelativeLayout>

</com.flipboard.bottomsheet.BottomSheetLayout>


上层Java代码:

package zhangphil.demo;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.flipboard.bottomsheet.BottomSheetLayout;
import com.flipboard.bottomsheet.commons.ImagePickerSheetView;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MainActivity extends AppCompatActivity {

private static final int REQUEST_STORAGE = 0;
private static final int REQUEST_IMAGE_CAPTURE = REQUEST_STORAGE + 1;
private static final int REQUEST_LOAD_IMAGE = REQUEST_IMAGE_CAPTURE + 1;
protected BottomSheetLayout bottomSheetLayout;
private Uri cameraImageUri = null;
private ImageView selectedImage;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottomSheetLayout = (BottomSheetLayout) findViewById(R.id.bottomsheet);
bottomSheetLayout.setPeekOnDismiss(true);
selectedImage = (ImageView) findViewById(R.id.image_picker_selected);
findViewById(R.id.image_picker_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (checkNeedsPermission()) {
requestStoragePermission();
} else {
showSheetView();
}
}
});
}

private boolean checkNeedsPermission() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED;
}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void requestStoragePermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_STORAGE);
} else {
// Eh, prompt anyway
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_STORAGE);
}
}

@TargetApi(Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQUEST_STORAGE) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
showSheetView();
} else {
// Permission denied
Toast.makeText(this, "Sheet is useless without access to external storage :/", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

/**
* Show an {@link ImagePickerSheetView}
*/
private void showSheetView() {
ImagePickerSheetView sheetView = new ImagePickerSheetView.Builder(this)
.setMaxItems(30)
.setShowCameraOption(createCameraIntent() != null)
.setShowPickerOption(createPickIntent() != null)
.setImageProvider(new ImagePickerSheetView.ImageProvider() {
@Override
public void onProvideImage(ImageView imageView, Uri imageUri, int size) {
Glide.with(MainActivity.this)
.load(imageUri)
.centerCrop()
.crossFade()
.into(imageView);
}
})
.setOnTileSelectedListener(new ImagePickerSheetView.OnTileSelectedListener() {
@Override
public void onTileSelected(ImagePickerSheetView.ImagePickerTile selectedTile) {
bottomSheetLayout.dismissSheet();
if (selectedTile.isCameraTile()) {
dispatchTakePictureIntent();
} else if (selectedTile.isPickerTile()) {
startActivityForResult(createPickIntent(), REQUEST_LOAD_IMAGE);
} else if (selectedTile.isImageTile()) {
showSelectedImage(selectedTile.getImageUri());
} else {
genericError();
}
}
})
.setTitle("选择一张照片...")
.create();

bottomSheetLayout.showWithSheetView(sheetView);
}

/**
* For images captured from the camera, we need to create a File first to tell the camera
* where to store the image.
*
* @return the File created for the image to be store under.
*/
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File imageFile = File.createTempFile(
imageFileName,  /* prefix */
".jpg",         /* suffix */
storageDir      /* directory */
);

// Save a file: path for use with ACTION_VIEW intents
cameraImageUri = Uri.fromFile(imageFile);
return imageFile;
}

/**
* This checks to see if there is a suitable activity to handle the `ACTION_PICK` intent
* and returns it if found. {@link Intent#ACTION_PICK} is for picking an image from an external app.
*
* @return A prepared intent if found.
*/
@Nullable
private Intent createPickIntent() {
Intent picImageIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
if (picImageIntent.resolveActivity(getPackageManager()) != null) {
return picImageIntent;
} else {
return null;
}
}

/**
* This checks to see if there is a suitable activity to handle the {@link MediaStore#ACTION_IMAGE_CAPTURE}
* intent and returns it if found. {@link MediaStore#ACTION_IMAGE_CAPTURE} is for letting another app take
* a picture from the camera and store it in a file that we specify.
*
* @return A prepared intent if found.
*/
@Nullable
private Intent createCameraIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
return takePictureIntent;
} else {
return null;
}
}

/**
* This utility function combines the camera intent creation and image file creation, and
* ultimately fires the intent.
*
* @see {@link #createCameraIntent()}
* @see {@link #createImageFile()}
*/
private void dispatchTakePictureIntent() {
Intent takePictureIntent = createCameraIntent();
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent != null) {
// Create the File where the photo should go
try {
File imageFile = createImageFile();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imageFile));
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
} catch (IOException e) {
// Error occurred while creating the File
genericError("Could not create imageFile for camera");
}
}
}

@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
Uri selectedImage = null;
if (requestCode == REQUEST_LOAD_IMAGE && data != null) {
selectedImage = data.getData();
if (selectedImage == null) {
genericError();
}
} else if (requestCode == REQUEST_IMAGE_CAPTURE) {
// Do something with imagePath
selectedImage = cameraImageUri;
}

if (selectedImage != null) {
showSelectedImage(selectedImage);
} else {
genericError();
}
}
}

private void showSelectedImage(Uri selectedImageUri) {
selectedImage.setImageDrawable(null);
Glide.with(this)
.load(selectedImageUri)
.crossFade()
.fitCenter()
.into(selectedImage);
}

private void genericError() {
genericError(null);
}

private void genericError(String message) {
Toast.makeText(this, message == null ? "Something went wrong." : message, Toast.LENGTH_SHORT).show();
}

}


由于需要读取设备图象文件,须增加权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


本例中在加载图片时候使用了Glide,关于Glide,请查阅附录文章4。

代码运行结果--->

初始化状态:



点击button按钮弹出选择面板:



拖曳向上铺满窗口:



本例中的照片选取代码是一个相对比较独立、可以单独抽取出去的通用模块化代码,支持从图库中选取,也支持调用相机拍照出图,在其他项目中使用,只需要关注诸如本例中的button按钮事件以及最终的图片加载位置,就可以在自己的项目灵活使用。

附录文章:

1,《Android自底部平滑向上滑出面板的AndroidSlidingUpPanel》链接地址:http://blog.csdn.net/zhangphil/article/details/51444509

2,《Android音乐、视频类APP常用控件:DraggablePanel(1)》链接地址:http://blog.csdn.net/zhangphil/article/details/51566860

3,《Android音乐、视频类APP常用控件:DraggablePanel(2)》链接地址:http://blog.csdn.net/zhangphil/article/details/51578665

4,《Android图片加载与缓存开源框架:Android Glide》链接地址http://blog.csdn.net/zhangphil/article/details/45535693

5,《Android BottomSheet:便捷易用的底部滑出面板(1)》链接地址:http://blog.csdn.net/zhangphil/article/details/51775955
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: