Android ListView,带有来自相机或图库的自定义图像

时间:2014-10-09 12:02:23

标签: android listview android-camera scrollview android-gallery

我制作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项目超过显示尺寸时,滚动不能顺利进行。或者可以为图像制作更强大的压缩效果?怎么会更好。 是否有可能实现&#34;从相机拍摄照片&#34;没有STORAGE清单中的权限?

提前谢谢!

/ 变化 /

我也使用这个功能,改变对象的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));
    }

1 个答案:

答案 0 :(得分:0)

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

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

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

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

有关此内容的更多信息:http://developer.android.com/training/improving-layouts/smooth-scrolling.html