title: Android ListView with custom images from Camera or Gallery
body: <p>I making ListView with possibility add images from camera or gallery. All works fine, but scrolling works not so smooth.</p>
  
  <p>here is my code:</p>
  
  <pre><code>public boolean onMenuItemClick(MenuItem item) {
  
          switch (item.getItemId()) {
  
              case R.id.context_rename:
                   renameDialog(selectedItem);
                   return true;
  
              case R.id.context_set_foto:
                   selectImage();
                   return true;
  
              default:
                   return false;
          }
  }
  
   private void selectImage() {
  
          final CharSequence[] options = { getString(R.string.takeAFoto), getString(R.string.chooseFromGallery),getString(R.string.dialogUserCancel) };
  
          AlertDialog.Builder builder = new AlertDialog.Builder(List.this);
  
          builder.setTitle(getString(R.string.addFoto));
  
          builder.setItems(options, new DialogInterface.OnClickListener() {
  
              @Override
  
              public void onClick(DialogInterface dialog, int item) {
  
                  if (options[item].equals(getString(R.string.takeAFoto))) {
  
  
                      //define the file-name to save photo taken by Camera activity
                      String fileName = "new-photo-name.jpg";
                      //create parameters for Intent with filename
                      ContentValues values = new ContentValues();
                      values.put(MediaStore.Images.Media.TITLE, fileName);
                      values.put(MediaStore.Images.Media.DESCRIPTION,"Image captured by camera");
                      //imageUri is the current activity attribute, define and save it for later usage (also in onSaveInstanceState)
                      imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
                      //create new Intent
                      Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                      intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                      intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
                      startActivityForResult(intent, 1);
  
                  }
  
                  else if (options[item].equals(getString(R.string.chooseFromGallery))) {
  
                      try {
                          Intent gintent = new Intent();
                          gintent.setType("image/*");
                          gintent.setAction(Intent.ACTION_GET_CONTENT);
                          startActivityForResult(
                                  Intent.createChooser(gintent, "Select Picture"),
                                  2);
                      } catch (Exception e) {
                          Toast.makeText(getApplicationContext(),
                                  e.getMessage(),
                                  Toast.LENGTH_LONG).show();
                          Log.e(e.getClass().getName(), e.getMessage(), e);
                      }
  
                  }
  
                  else if (options[item].equals(getString(R.string.dialogUserCancel))) {
  
                      dialog.dismiss();
  
                  }
  
              }
  
          });
  
          builder.show();
  
      }
  
  @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  
          super.onActivityResult(requestCode, resultCode, data);
  
          Uri selectedImageUri = null;
          String filePath = null;
  
          if (resultCode == RESULT_OK) {
  
              if (requestCode == 1) {
  
                  if (resultCode == RESULT_OK) {
                      //use imageUri here to access the image
                      selectedImageUri = imageUri;
  
                  } else if (resultCode == RESULT_CANCELED) {
                      Toast.makeText(this, "Picture was not taken", Toast.LENGTH_SHORT).show();
                  } else {
                      Toast.makeText(this, "Picture was not taken", Toast.LENGTH_SHORT).show();
                  }
  
              } else if (requestCode == 2) {
  
                  selectedImageUri = data.getData();
  
              }
  
              if(selectedImageUri != null){
                  try {
                      // OI FILE Manager
                      String filemanagerstring = selectedImageUri.getPath();
  
                      // MEDIA GALLERY
                      String selectedImagePath = getPath(selectedImageUri);
  
                      if (selectedImagePath != null) {
                          filePath = selectedImagePath;
                      } else if (filemanagerstring != null) {
                          filePath = filemanagerstring;
                      } else {
                          Toast.makeText(getApplicationContext(), "Unknown path",
                                  Toast.LENGTH_LONG).show();
                          Log.e("Bitmap", "Unknown path");
                      }
  
                      if (filePath != null) {
                          decodeFile(filePath);
                      } else {
                          bitmap = null;
                      }
                  } catch (Exception e) {
                      Toast.makeText(getApplicationContext(), "Internal error",
                              Toast.LENGTH_LONG).show();
                      Log.e(e.getClass().getName(), e.getMessage(), e);
                  }
              }
  
          }
  
      }
  
      public String getPath(Uri uri) {
          String res = null;
          String[] proj = { MediaStore.Images.Media.DATA };
          Cursor cursor = getContentResolver().query(uri, proj, null, null, null);
          if(cursor.moveToFirst()){;
              int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
              res = cursor.getString(column_index);
          }
          cursor.close();
          return res;
      }
  
      public void decodeFile(String filePath) {
          // Decode image size
          BitmapFactory.Options o = new BitmapFactory.Options();
          o.inJustDecodeBounds = true;
          BitmapFactory.decodeFile(filePath, o);
          // The new size we want to scale to
          final int REQUIRED_SIZE = 1024;
          // Find the correct scale value. It should be the power of 2.
          int width_tmp = o.outWidth, height_tmp = o.outHeight;
          int scale = 1;
          while (true) {
              if (width_tmp &lt; REQUIRED_SIZE &amp;&amp; height_tmp &lt; REQUIRED_SIZE)
                  break;
              width_tmp /= 2;
              height_tmp /= 2;
              scale *= 2;
          }
          // Decode with inSampleSize
          BitmapFactory.Options o2 = new BitmapFactory.Options();
          o2.inSampleSize = scale;
          bitmap = BitmapFactory.decodeFile(filePath, o2);
          prod_image.setImageBitmap(bitmap);
          replaceBitmapInArray(bitmap);
      }
  </code></pre>
  
  <p>When listview item more than size of display, scrolling doesn't work smoothly. Or maybe make more strong compress for images? How will be better.
  And is it possible realize "Take foto from camera" without permissions in manifest for STORAGE?</p>
  
  <p>Thx in advance!</p>
  
  <p>/<em>CHANGES</em>/</p>
  
  <p>i'm using this function too, for changes in Arraylist of objects</p>
  
  <pre><code>private void replaceBitmapInArray(Bitmap bitmap){
  
          Product p = productsArray.get(selectedPosition);
  
          ByteArrayOutputStream bos = new ByteArrayOutputStream();
          bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
          byte[] bArray = bos.toByteArray();
  
          p.setProdImage(bArray);
  
          productsArray.set(selectedPosition,p);
  
          animAdapter.notifyDataSetChanged();
  
      }
  </code></pre>
  
  <p>and Adapter's code:</p>
  
  <pre><code>public class MyListAdapter extends ArrayAdapter&lt;Product&gt; implements UndoAdapter {
  
      private final Context mContext;
      HashMap&lt;Product, Integer&gt; mIdMap = new HashMap&lt;Product, Integer&gt;();
      ArrayList&lt;Product&gt; products = new ArrayList&lt;Product&gt;();
      final int INVALID_ID = -1;
      LayoutInflater lInflater;
  
      public MyListAdapter(Context context, int textViewResourceId, List&lt;Product&gt; prod) {
          //super(context, textViewResourceId, prod);
          super(prod);
          lInflater = (LayoutInflater) context
                  .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          mContext = context;
          for (int i = 0; i &lt; prod.size(); i++) {
              //add(prod.get(i));
              mIdMap.put(prod.get(i),i);
          }
      }
  
      @Override
      public long getItemId(final int position) {
          //return getItem(position).hashCode();
          Product item = (Product) getItem(position);
          return mIdMap.get(item);
      }
  
      @Override
      public boolean hasStableIds() {
          return true;
      }
  
      @Override
      public View getView(final int position, View convertView, final ViewGroup parent) {
          //TextView view = (TextView) convertView;
          /*View view = convertView;
          if (view == null) {
              //view = (TextView) LayoutInflater.from(mContext).inflate(R.layout.list_row, parent, false);
              view = lInflater.inflate(R.layout.item, parent, false);
              view.setBackgroundResource(R.drawable.rounded_corners);
  
              Product p = getItem(position);
  
              //view.setText(getItem(position).getProductName());
              ((TextView) view.findViewById(R.id.tvDescr)).setText(p.getProductName());
              ((ImageView) view.findViewById(R.id.ivImage)).setImageResource(p.getProductImage());
  
              if(p.getProductImageBitmap() != null) {
  
                  if (p.getProductImageBitmap().length &gt; 0) {
                      Bitmap bmp = BitmapFactory.decodeByteArray(p.getProductImageBitmap(), 0, p.getProductImageBitmap().length);
                      ImageView image = (ImageView) view.findViewById(R.id.list_image);
                      image.setImageBitmap(bmp);
                  }
  
              }
  
  
              ImageView iv = (ImageView)view.findViewById(R.id.ivImage);
              iv.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View view) {
                      MyListAdapter.this.remove(getItem(position));
                      Product p = getItem(position);
                      Toast.makeText(mContext, p.getProductName() + " " + mContext.getString(R.string.deleted_item), Toast.LENGTH_SHORT).show();
                      MyListAdapter.this.notifyDataSetChanged();
                  }
              });
  
          }
  
          return view;*/
  
          ViewHolder holder = null;;
          Product p = getItem(position);
  
          if (convertView == null) {
  
              convertView = lInflater.inflate(R.layout.item, null);
              convertView.setBackgroundResource(R.drawable.rounded_corners);
              holder = new ViewHolder();
  
              holder.tvDescr = (TextView) convertView.findViewById(R.id.tvDescr);
              holder.list_image = (ImageView) convertView.findViewById(R.id.list_image);
              holder.products_amount = (TextView) convertView.findViewById(R.id.products_amount);
              holder.products_price = (TextView) convertView.findViewById(R.id.products_price);
              holder.ivImage = (ImageView) convertView.findViewById(R.id.ivImage);
  
              convertView.setTag(holder);
  
          } else {
  
              holder = (ViewHolder) convertView.getTag();
  
          }
  
          if (p.getProductImageBitmap() != null &amp;&amp; p.getProductImageBitmap().length &gt; 0) {
              Bitmap bmp = BitmapFactory.decodeByteArray(p.getProductImageBitmap(), 0, p.getProductImageBitmap().length);
              holder.list_image.setImageBitmap(bmp);
          } else {
              holder.list_image.setImageResource(R.drawable.ic_launcher);
          }
  
          holder.tvDescr.setText(p.getProductName());
  
          holder.ivImage.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View view) {
  
                  String deletedItem = getItem(position).getProductName();
                  MyListAdapter.this.remove(getItem(position));
  
                  if (MyListAdapter.this.getCount() &gt; 0) {
  
                      Toast.makeText(mContext, deletedItem + " " + mContext.getString(R.string.deleted_item), Toast.LENGTH_SHORT).show();
                      MyListAdapter.this.notifyDataSetChanged();
  
                  } else {
  
                      Toast.makeText(mContext,mContext.getString(R.string.sklerolist_empty), Toast.LENGTH_SHORT).show();
  
                  }
  
              }
          });
  
          return convertView;
      }
  
      static class ViewHolder {
          ImageView list_image;
          TextView tvDescr;
          TextView products_amount;
          TextView products_price;
          ImageView ivImage;
      }
  
      @NonNull
      @Override
      public View getUndoView(final int position, final View convertView, @NonNull final ViewGroup parent) {
          View view = convertView;
          if (view == null) {
              //view = LayoutInflater.from(mContext).inflate(R.layout.undo_row, parent, false);
              view = lInflater.inflate(R.layout.undo_row, parent, false);
          }
          return view;
      }
  
      @NonNull
      @Override
      public View getUndoClickView(@NonNull final View view) {
          return view.findViewById(R.id.undo_row_undobutton);
      }
  </code></pre>
  
  <p>and function SetAdapter:</p>
  
  <pre><code>private void setAdapter(){
          final com.nhaarman.listviewanimations.ArrayAdapter&lt;Product&gt; adapter = new MyListAdapter(this,R.layout.text_view,productsArray);
          SimpleSwipeUndoAdapter simpleSwipeUndoAdapter = new SimpleSwipeUndoAdapter(adapter, this, new MyOnDismissCallback(adapter));
          animAdapter = new AlphaInAnimationAdapter(simpleSwipeUndoAdapter);
          animAdapter.setAbsListView(listView);
          assert animAdapter.getViewAnimator() != null;
          animAdapter.getViewAnimator().setInitialDelayMillis(INITIAL_DELAY_MILLIS);
          listView.setAdapter(animAdapter);
          /* Enable drag and drop functionality */
          listView.enableDragAndDrop();
          listView.setDraggableManager(new TouchViewDraggableManager(R.id.list_row_draganddrop_touchview));
          listView.setOnItemMovedListener(new MyOnItemMovedListener(adapter));
          listView.setOnItemLongClickListener(new MyOnItemLongClickListener(listView));
          /* Enable swipe to dismiss */
          listView.enableSimpleSwipeUndo();
          /* Add new items on item click */
          //listView.setOnItemClickListener(new MyOnItemClickListener(listView));
      }
  </code></pre>