如何使用Uri和Bitmap Factory将图像加载到imageView中

时间:2016-09-29 21:26:43

标签: android imageview

我正在将Uri传递给新活动并尝试使用它在新活动中创建imageView。我使用InputStream和BitmapFactory来实现这一点。不过,我的照片显示为黑色,我不知道为什么。

First_Page:

public void galleryClicked(View view){

    Intent intent = new Intent(Intent.ACTION_PICK);

    File pictureDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    String pictureDirectoryPath = pictureDirectory.getPath();

    Uri data = Uri.parse(pictureDirectoryPath);

    intent.setDataAndType(data, "image/*");

    startActivityForResult(intent, GALLERY_REQUEST);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if(resultCode == RESULT_OK ){
        Intent intent = new Intent(this, Tattoo_Page.class);
        intent.putExtra("picture", data.getData());
        startActivity(intent);
    }
}

Tattoo_Page:

public class Tattoo_Page extends Activity {

private ImageView picture;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.tattoo_page);

    Bundle extras = getIntent().getExtras();
    picture = (ImageView) findViewById(R.id.picture);

    Uri imageUri = (Uri) extras.get("picture");


    try {

        InputStream inputStream = getContentResolver().openInputStream(imageUri);

        Bitmap image = BitmapFactory.decodeStream(inputStream);

        picture.setImageBitmap(image);

    } catch (FileNotFoundException e) {
        e.printStackTrace();
        Toast.makeText(this, "Unable to open image", Toast.LENGTH_LONG).show();
    }

}

}

XML:

<ImageView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/picture"
    android:scaleType="fitCenter"/>

清单:

<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-feature android:name="android.hardware.camera2" />
<uses-feature android:name="android.hardware.camera.any" />


<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/Theme.AppCompat.NoActionBar"
    android:screenOrientation="portrait">
    <activity android:name=".First_Page">

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity android:name=".Tattoo_Page"> </activity>

</application>

2 个答案:

答案 0 :(得分:2)

您可以使用以下代码执行确切的任务:

public void galleryClicked(View v){
    Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(Intent.createChooser(intent, "Complete action using"), 0);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 0 && resultCode == getActivity().RESULT_OK) {
        Uri selectedImageUri = data.getData();
        String[] fileColumns = {MediaStore.Images.Media.DATA};
        Cursor cursor = getActivity().getContentResolver().query(selectedImageUri, fileColumns, null, null, null);
        cursor.moveToFirst();
        int cIndex = cursor.getColumnIndex(fileColumns[0]);
        String picturePath = cursor.getString(cIndex);
        cursor.close();
        if (picturePath != null) {
            Intent intent = new Intent(this, Tattoo_Page.class);
            intent.putExtra("picture", picturePath);
            startActivity(intent);
        }
    }
}

Tatoo_Page活动

public class Tattoo_Page extends Activity {

public static int IMAGE_MAX_WIDTH=1024;
public static int IMAGE_MAX_HEIGHT=768;
private ImageView picture;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.tattoo_page);

Bundle extras = getIntent().getExtras();
picture = (ImageView) findViewById(R.id.picture);

String imagePath =  extras.getStringExtra("picture");


new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                final Bitmap bitmap = decodeFile(new File(picturePath));
                if (bitmap != null) {
                    Tatoo_Page.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            picture.setImageBitmap(bitmap);
                        }
                    });
                }else{
                        Toast.makeText(Tatoo_page.this,"Error",Toast.LENGTH_SHORT).show();
                }
            }catch(Exception e){
                e.printStackTrace();
                Toast.makeText(ProfileFragment.this.getActivity(),"Problem loading file",Toast.LENGTH_SHORT).show();
            }
        }
    }).start();

}
//This function will decode the file stream from path with appropriate size you need. 
//Specify the max size in the class 
private Bitmap decodeFile(File f) throws Exception{
    Bitmap b = null;

    //Decode image size
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;

    FileInputStream fis = new FileInputStream(f);
    BitmapFactory.decodeStream(fis, null, o);
    fis.close();

    int scale = 1;
    int IMAGE_MAX_SIZE=Math.max(IMAGE_MAX_HEIGHT,IMAGE_MAX_WIDTH);
    if (o.outHeight > IMAGE_MAX_HEIGHT || o.outWidth > IMAGE_MAX_WIDTH) {
        scale = (int)Math.pow(2, (int) Math.ceil(Math.log(IMAGE_MAX_SIZE /
                (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
    }

    //Decode with inSampleSize
    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize = scale;
    fis = new FileInputStream(f);
    b = BitmapFactory.decodeStream(fis, null, o2);
    fis.close();

    return b;
}

答案 1 :(得分:1)

您正在访问主线程中的图像。它非常不合适,因为它可能会降低您的应用速度,并可能会降低帧速率,直到内存加载完成。

有一个很棒的库,可以在子线程中抽象整个过程并将其应用到布局中。

输入Picasso。通过将compile 'com.squareup.picasso:picasso:2.5.2'添加到项目依赖项中,将它包含到项目中,然后只需编写这个简单的行来从Web下载图像:

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

在处理磁盘映像时,您可能需要使用此加载程序:

Picasso.with(context).load(new File(...)).into(imageView);

就是这样。你完成了。

作为奖励,Picasso自动处理Android上许多常见的图像加载陷阱::

  • 在适配器中处理ImageView回收和下载取消。
  • 使用最少内存的复杂图像转换。
  • 自动内存和磁盘缓存。

此外,它非常快速和轻巧。比那里的几乎任何实现快得多(如果不是更快),整个jar文件只有118 kb。

<强> TL; DR:

使用Picasso。所有很酷的孩子都在这样做。