【问题标题】:How to pass drawable between activities如何在活动之间传递drawable
【发布时间】:2011-12-06 21:48:34
【问题描述】:

如何在活动之间传递图像、可绘制类型?

我试试这个:

private Drawable imagen;

Bundle bundle = new Bundle();
bundle.putSerializable("imagen", (Serializable) unaReceta.getImagen());
Intent myIntent = new Intent(v.getContext(), Receta.class);
myIntent.putExtras(bundle);
startActivityForResult(myIntent, 0);

但它向我报告了一个 execption:

java.lang.ClassCastException: android.graphics.drawable.BitmapDrawable

【问题讨论】:

    标签: android android-activity drawable


    【解决方案1】:

    1) 作为extras

    传递intent

    Activity A 中,您将图像解码并通过 Intent 发送:

    • 使用此方法(额外)图像在 162 毫秒的时间间隔内传递
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);     
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); 
    byte[] b = baos.toByteArray();
    
    Intent intent = new Intent(this, ActivityB.class);
    intent.putExtra("picture", b);
    startActivity(intent);
    

    Activity B 中,您会收到带有字节数组(解码图片)的意图,并将其作为源应用到 ImageView:

    Bundle extras = getIntent().getExtras();
    byte[] b = extras.getByteArray("picture");
    
    Bitmap bmp = BitmapFactory.decodeByteArray(b, 0, b.length);
    ImageView image = (ImageView) findViewById(R.id.imageView1);
    
    image.setImageBitmap(bmp);
    

    2)保存图像文件并将其引用传递给另一个活动

    "大小限制是:尽量小。绝对不要放 除非它不大于图标(32x32 或 随便)。

    • 在*Activity A* 中保存文件(内部存储)
    String fileName = "SomeName.png";
    try {
        FileOutputStream fileOutStream = openFileOutput(fileName, MODE_PRIVATE);
        fileOutStream.write(b);  //b is byte array 
                                 //(used if you have your picture downloaded
                                 // from the *Web* or got it from the *devices camera*)
                                 //otherwise this technique is useless
        fileOutStream.close();
    } catch (IOException ioe) {
        ioe.printStackTrace();
    }
    
    • 将位置作为字符串传递给活动 B
    Intent intent = new Intent(this, ActivityB.class);
    intent.putExtra("picname", fileName);
    
    • 在 *Activity B* 中检索文件
    Bundle extras = getIntent().getExtras();
    String fileName = extras.getString("picname");
    
    • 使*drawable*脱离图片
    File filePath = getFileStreamPath(fileName);
    Drawable d = Drawable.createFromPath(filePath.toString());
    
    • 应用到 ImageView 资源
    someImageView.setBackgroundDrawable(d);
    

    【讨论】:

    • 这对大图像有效吗?以及如何将位图传递给 Bundle()?
    • @user548834 你按照我在示例中展示的那样进行操作 - 你将其解码为字节数组并将字节数组附加到意图,然后在另一侧检索它(另一个活动)。这取决于图像、简单图标或数码相机照片之类的大小。如果我们谈论的是照片,那么保存为文件是更好的主意
    • 这个答案明确显示了如何序列化位图并将其作为意图的一部分传递。它没有回答为什么程序员可能想要避免这种情况。但这绝对是答案。
    • @Mocialov Boris - 很棒的编辑,谢谢。总结一下:只传递意图中的小图像。对于较大的图像,通过参考传递。除非意图由单独的应用程序处理,否则在所有情况下都可以通过引用传递。但是对于这种情况,使用公共设备存储可能会有更好的解决方案。
    • @ZiaUrRahman openFileOutput() 函数驻留在您的活动的Context 中。就做myActivity.openFileOutput(...)
    【解决方案2】:

    您可以使用图像资源名称(如“img1.png”)标记每个图像(在 xml 中,或以编程方式), 然后使用getTag();检索图像名称

    然后使用getResources().getIdentifier(image name,"drawable", .getPackageName())获取可绘制资源id。

    并且只需通过意图传递资源 id -

    intent.putExtra("img 1",resource id);
    

    最后,Activity 可以使用以下资源从资源中创建图像:

    getResources().getDrawable(intent.getIntExtra("img 1",-1));    
    

    【讨论】:

      【解决方案3】:

      Drawable 对象本质上不是可序列化的,因此它们不能直接在Intent extras 中传递。您必须找到另一种方法来序列化或持久化图像数据并在新的 Activity 中检索它。

      例如,如果您正在使用BitmapDrawable 实例,则可以将底层Bitmap 写入文件并读回,或序列化为字节数组(如果它足够小),并且字节数组可以是通过 Intent 的附加值传递。

      HTH

      【讨论】:

      • 文件绝对是这里更好的选择,intent extras应该尽可能小,因为performance reasons
      • 位图如何写入文件并读回?图片很大,所以我需要一个有效的解决方案。
      • Bitmap.compress() 将数据写入文件,BitmapFactory.decodeFile() 将数据读回内存。 Bitmap.compress() 也可用于将数据写入字节数组...只是 OutputStream 的不同类型。如果这还不够快,您将需要创建一个全局内存位置(可能是应用程序中的静态字段)来存储转换期间的信息。不过要小心静态内存,以免造成不必要的泄漏。
      • 通过第一步,清晰度显着降低,有什么建议可以改善吗?
      【解决方案4】:

      最好不要在Activities 之间传递(或序列化)Drawables。您很可能正在从资源中获取可绘制对象。因此有一个资源ID。而是传递它,那只是一个整数。并在 另一个 Activity 中重新补水 Drawable

      如果Drawable 不是来自资源,而是在运行时在内存中构建...那么让我们谈谈它。 @Devunwired 在这种情况下有一个很好的建议。

      【讨论】:

      • 如何获取另一个应用程序图标的资源id?!
      • 直接回答是我不知道。间接的一个是:我不确定你能做到这一点,我什至不确定它是否有意义。如果你在同一个项目源、同一个应用程序的上下文中,我猜资源 ID 主要是有意义的,所以你可以访问 APK 中嵌入的同一个公共资源。
      【解决方案5】:

      如果您从网络中提取这些图像并一次又一次地加载它们,缓存它们将是一个非常好的选择,因为您将减少网络流量并提高加载速度。我建议使用Droid-Fu 中的WebImageView。非常好的解决方案,在一些项目中使用过,我很满意。

      【讨论】:

        【解决方案6】:

        我不知道是不是这种情况,但是如果您尝试传递drawable的原因是因为您使用的是Imageview,只需将资源ID放在imageview的标签中,将标签作为整数传递而不是意图的额外内容中的drawable,并在接收活动中使用以下行: imageView.setImageDrawable(getResources().getDrawable(getIntent().getIntExtra("image_id",0)));

        希望对某人有所帮助。

        【讨论】:

          【解决方案7】:

          您可以简单地使用原生的buildDrawingCache 方法:

              ImageView imageView = imageLayout.findViewById (R.id.img_thumb);
              imageView.buildDrawingCache ();
          
              Bundle extras = new Bundle ();
              extras.putParcelable ("image", imageView.getDrawingCache ());
          
              Intent intent = new Intent (this, ImageActivity.class);
              intent.putExtras (extras);
          
              startActivity (intent);
          

          然后在您的 ImageActivity 中获取它:

              Bundle bundle = getIntent ().getExtras ();
          
              if (bundle != null) {
          
                  ImageView imageView = findViewById (R.id.img_full);
          
                  Bitmap image = bundle.getParcelable ("image");
                  imageView.setImageBitmap (image);
          
              }
          

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-01-07
          • 2013-06-11
          • 2013-02-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多