Android BottomSheet:以选取图片为例(2)
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
Android BottomSheet:以选取图片为例(2)的更多相关文章
- Android BottomSheet:底部弹出Fragment面板(4)
Android BottomSheet:底部弹出Fragment面板(4) BottomSheet不仅可以弹出轻量级的定制好的面板(见附录文章5,6,7),还可以弹出"重"的 ...
- Android BottomSheet:List列表或Grid网格展示(3)
Android BottomSheet:List列表或Grid网格展示(3) BottomSheet可以显示多种样式的底部弹出面板风格,比如常见的List列表样式或者Grid网格样式,以一个例子 ...
- Android BottomSheet:便捷易用的底部滑出面板(1)
Android BottomSheet:便捷易用的底部滑出面板(1) Android BottomSheet是github上的一个第三方开源项目,其主页:https://github.com/Flip ...
- Ubuntu 14.04 Android 使用Maven一个 用例project
在说明书前面描述SDK通过使用Ant发展. 本文试图在此基础上使用Maven发展. 在这里,我们需要使用maven-android-plugin. 在本文中,参考官方文件: https://code. ...
- android一个上传图片的样例,包含怎样终止上传过程,假设在上传的时候更新进度条(一)
先上效果图: Layout为: <? xml version="1.0" encoding="utf-8"?> <LinearLayout x ...
- 创建android画笔程序的样例(有镜面效果)
先上图: 关键是在检測到手指移动的时候用mPath.quadTo的方法,android sdk解释是: Add a quadratic bezier from the last point, appr ...
- android发送短信样例
Android应用开发中我们经常须要发送手机短信.这对于android平台来说,是最简单只是的功能了,无需太多代码,也无需自己定义代码,仅仅须要调用android提供的消息管理类SmsManager就 ...
- android自定义控件——以滑动开关为例
0.引言 (1)Android从4.0开始提供了switch的滑动开关效果组件,但是之前版本却没有 (2)很多时候我们写程序,都希望把有用的通用的通用的东西封装起来,以便以后重用. 本文根据组件开发思 ...
- 基于Android Fragment功能的样例
通过近期空暇时候对Fragment的学习,尝试着写了一个小Demo,将在开发的时候能经常使用到的Fragment知识放在一起,写过了这个Demo对Android Fragment的了解更加深入了,以后 ...
随机推荐
- E20171123-sl
conform vi. 符合; 遵照; 适应环境; vi. 符合; 遵照; 适应环境; adj. 一致的; 顺从的; investigat ...
- select多选
1.css <style> .divBox{ width:400px; margin:100px auto; } .divBox span{ vertical-align:top; dis ...
- TensorFlow---基础---GFile
使用TensorFlow的时候经常遇到 tf.gfile.exists().... 关于gfile,一个googler是这样给出的解释: The main roles of the tf.gfile ...
- CF814B An express train to reveries
思路: 模拟,枚举. 实现: #include <iostream> using namespace std; ; int a[N], b[N], cnt[N], n, x, y; int ...
- Pro ASP.NET Core MVC 第6版 第二章(前半章)
目录 第二章 第一个MVC 应用程序 学习一个软件开发框架的最好方法是跳进他的内部并使用它.在本章,你将用ASP.NET Core MVC创建一个简单的数据登录应用.我将它一步一步地展示,以便你能看清 ...
- 常用css属性总结
边框修饰:border------>top,bottom,left,right上下左右边框 分为:color,类型style{ groove,dashed,ridge,solid}一个值---- ...
- DIV自动居中
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Java Servlet DAO实践(二)
Java Servlet DAO实践(二) DAO连接类 package com.seller.servlets.dao; import java.sql.*; public class DataBa ...
- ThinkPHP---thinkphp拓展之空操作
[一]概论 (1)定义 空操作指系统在找不到指定操作方法的时候.会定位到空操作方法 / 控制器来执行,利用这个机制,我们可以实现错误页面的自定义和URL的优化 (2)场景 常用于错误页面的自定义 (3 ...
- Description Resource Path Location Type Missing artifact com.********:framework:jar:1.0.2 pom.xml /项目名 line **** Maven Dependency Problem
问题具体描述如下图所示: 对于该问题本人是这么解决的. 在window下[Preferences]目录找到[Maven]下的[usersetting] 查看local repository 里面的路径 ...