我制作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));
}
答案 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