2014-10-09 98 views
0

我让ListView可以添加来自相机或图库的图像。所有的工作都很好,但滚动效果并不那么顺利。Android ListView与来自相机或图库的自定义图像

这里是我的代码:

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 < REQUIRED_SIZE && height_tmp < 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); 
    } 

当ListView项比显示的尺寸更大,滚动不工作的顺利开展。或者,也许更强大的图像压缩?怎么会更好。 是否有可能实现“从相机拍摄”没有权限清单存储?

Thx提前!

/CHANGES/

我使用这个功能也为改变ArrayList的对象

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(); 

    } 

和适配器的代码:

public class MyListAdapter extends ArrayAdapter<Product> implements UndoAdapter { 

    private final Context mContext; 
    HashMap<Product, Integer> mIdMap = new HashMap<Product, Integer>(); 
    ArrayList<Product> products = new ArrayList<Product>(); 
    final int INVALID_ID = -1; 
    LayoutInflater lInflater; 

    public MyListAdapter(Context context, int textViewResourceId, List<Product> prod) { 
     //super(context, textViewResourceId, prod); 
     super(prod); 
     lInflater = (LayoutInflater) context 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     mContext = context; 
     for (int i = 0; i < 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 > 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 && p.getProductImageBitmap().length > 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() > 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); 
    } 

和功能SetAdapter:

private void setAdapter(){ 
     final com.nhaarman.listviewanimations.ArrayAdapter<Product> 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)); 
    } 

回答

0

在我看来,主要问题是方法decodeFile(String filePath)需要很长时间。在滚动系统期间等待它,并且滚动不平稳。

尝试在新线程中运行decodeFile(String filePath)(可以使用AsyncTask)。

编辑:方法getView被调用每次你滚动,添加项目或刷新listView。项目在getView结束后显示。如此长时间的运行操作(超过100毫秒)可能会导致不平滑的滚动。

这个长时间运行的操作(例如:解码位图图像)应该在新线程(AsyncTask)中运行。但由于适配器listView中的recycling views可以在线程结束之前显示旧图像。因此,在新线程启动之前,在getView中显示一些占位符图像(例如ProgressBar)是很好的。

更多关于这一点:http://developer.android.com/training/improving-layouts/smooth-scrolling.html

+0

THX,我会尝试写回 – kbu 2014-10-09 12:14:28

+0

我看了你的代码,但我不能老是看你的适配器和方法getView的代码。在我的情况下,问题在那里,我不得不使用新线程来加载图像在这种方法。 – vzoha 2014-10-09 12:21:33

+0

我在上面添加了更改。 – kbu 2014-10-09 12:33:01