我已经实现了一个自定义画廊,让用户可以实时选择许多图像,并将它们传递给一个新活动,在该活动中,为每个传递的图像实用地创建 ImageViews。用户可以自由添加多次图像。我注意到的是,如果用户每次都选择尚未选择的新图像,则一切正常。但是,如果用户选择了已经传递给下一个活动的图像,则应用程序崩溃并且我收到 java.lang.StringIndexOutOfBounds 错误。我需要了解导致此问题的原因。现在我添加我的代码,但如果您需要更好地理解,我可以编辑或添加更多。
自定义画廊:
public void onResume(){
super.onResume();
Intent previousIntent= getIntent(); //create a new intent for retrieve the photos path from the PhotoManagement activity (this need to be done for not lost the already selected images)
Bundle customGalleryIntentBundle = getIntent().getExtras();
if( customGalleryIntentBundle != null ){
photosPath = (String) customGalleryIntentBundle.get("Selected Images"); //get the selected images from the previous activity
photosPath = photosPath.replace("null", "");
Log.i("CUSTOM GALLERY PHOTOS PATH",""+photosPath);
}
final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID };
final String orderBy = MediaStore.Images.Media._ID;
Cursor imagecursor = managedQuery( //create the cursor for navigate inside the database device and retrieve informations about the media contents like photo, video ecc...
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null,
null, orderBy);
int image_column_index = imagecursor.getColumnIndex(MediaStore.Images.Media._ID); //get the current column index
this.count = imagecursor.getCount(); //count the external content uri of the cursor
this.thumbnails = new Bitmap[this.count]; //create an array of bitmap using the size retrieved from the count variable
this.arrPath = new String[this.count]; //create the array that contains the list of the path of the media (photos in this case)
this.thumbnailsselection = new boolean[this.count]; //initialize the array of boolean to save informations about the selection of the thumbnails
for (int i = 0; i < this.count; i++) {
imagecursor.moveToPosition(i); //let's start from the first position and move one by one until the end
int id = imagecursor.getInt(image_column_index);
int dataColumnIndex = imagecursor.getColumnIndex(MediaStore.Images.Media.DATA);
thumbnails[i] = MediaStore.Images.Thumbnails.getThumbnail( //take the thumbnails of the images and store it inside the array using the MICRO format for avoid high memory usage
getApplicationContext().getContentResolver(), id,
MediaStore.Images.Thumbnails.MICRO_KIND, null);
arrPath[i]= imagecursor.getString(dataColumnIndex);
}
GridView imagegrid = (GridView) findViewById(R.id.PhoneImageGrid); //assign the GridView to the equivalent element in the xml file
imageAdapter = new ImageAdapter(); //create a new imageAdapter. It is used how source for all the items in the gridView
imagegrid.setAdapter(imageAdapter);
imagecursor.close(); //close the image cursor when we arrive to the end of the columns to analize
final Button selectBtn = (Button) findViewById(R.id.selectBtn); //assign the button to the equivalent in the xml layout
selectBtn.setOnClickListener(new OnClickListener() { //create a listener for reveal when it is pressed
public void onClick(View v) {
// TODO Auto-generated method stub
final int len = thumbnailsselection.length;
int cnt = 0; //initialize a count for check the number of selected photos
String selectImages = "";
for (int i =0; i<len; i++)
{
if (thumbnailsselection[i]){
cnt++;
selectImages = selectImages + arrPath[i] + "|"; //store the correct path of the images in the variable (we can use this string for find the images path in others activity)
Log.i("CUSTOM GALLERY SELECT IMAGES",""+selectImages);
}
}
//if no one image is selected show a message to the user
if (cnt == 0){
Toast.makeText(getApplicationContext(),
"Please select at least one image",
Toast.LENGTH_LONG).show();
} else {
//If at least one image is selected we create a new activity where the images are displayed and the user can manage them
Intent photoManagementIntent = new Intent(
getApplicationContext(),
PhotoManagement.class //select the class for the next activity
);
photoManagementIntent.putExtra("Selected Images",""+selectImages+photosPath); //add an extra parameter that contains the path of the selected images. In this mode we can read it in the next activity
startActivity(photoManagementIntent); //start the new activity
}
}
});
}
这是我实用地创建 ImageViews 以显示从自定义画廊传递的图像的类:
protected void onResume(){
super.onResume();
Intent previousIntent= getIntent(); //create a new intent for retrieve informations from the previous activity
Bundle photoManagementIntentBundle = getIntent().getExtras();
if(photoManagementIntentBundle != null) //if the new intent is different from null
{
photosPath = (String) photoManagementIntentBundle.get("Selected Images"); //get the "selected images" string created in the previous activity
photosPath = photosPath.replace("null", "");
final String photosPathCopy = photosPath;
int count = photosPath.length() - photosPath.replace("|", "").length(); //count contains the number of images selected
//SCROLL VIEW
ScrollView scrollView = new ScrollView(this); //create a new scrollView
scrollView.setBackground(getResources().getDrawable(R.drawable.background)); //give the background gradient
scrollView.setLayoutParams(new ScrollView.LayoutParams(ScrollView.LayoutParams.MATCH_PARENT, //set the main params about the dynamic size of the scrollView
ScrollView.LayoutParams.MATCH_PARENT));
scrollView.setPadding(0, 20, 0, 0);
//LINEAR LAYOUT
LinearLayout linearLayout = new LinearLayout(this); //create a new linearLayout
linearLayout.setOrientation(LinearLayout.VERTICAL); //set the layout orientation
linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
for(int i=0; i<count; i++) {
int indexOf = photosPath.indexOf('|'); //take the number of characters from | char
String correctPath = photosPath.substring(0, indexOf); //this take the correct path of the photo
photosPath = photosPath.replace(correctPath+"|", ""); //replace the old path with nothing. In this mode at every loop we have a new path until the end.
Log.i("PHOTO MANAGEMENT PHOTOS PATH INSIDE LOOP",""+photosPath);
//RELATIVE LAYOUT
RelativeLayout relativeLayout = new RelativeLayout(this); //create a new relative layout
relativeLayout.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, //set main params about the width and height
RelativeLayout.LayoutParams.FILL_PARENT));
relativeLayout.setBackgroundColor(getResources().getColor(R.color.grayColor)); //set background color
LinearLayout.LayoutParams relativeParams = new LinearLayout.LayoutParams(
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
relativeParams.setMargins(20, 20, 20, 0);
relativeLayout.setLayoutParams(relativeParams); //set declared params about layout to the relativeLayout
relativeLayout.requestLayout();
relativeLayout.setOnClickListener(new View.OnClickListener(){ //create a listener about the layout. When a user press a point inside the relative layout a new activity should be created
@Override
public void onClick(View v){
Intent photoDetailsActivity = new Intent(
getApplicationContext(),
PhotoDetails.class //assign the class for create a new intent
);
photoDetailsActivity.putExtra("Selected Images",""+photosPathCopy);
startActivity(photoDetailsActivity); //let's start the new activity
}
});
//IMAGE VIEW
ImageView selectedPhoto = new ImageView(this); //create a new imageView
selectedPhoto.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT)); //set width and height params about the selected photo zone
try {
File standardImage = new File(correctPath); //create a new file with the original path of the images
BitmapFactory.Options o = new BitmapFactory.Options(); //Enable the Bitmap factory options
o.inJustDecodeBounds = true; //allow the caller to query the bitmap without having to allocate the memory for its pixels
BitmapFactory.decodeStream(new FileInputStream(standardImage),null,o); //decode the image using the bitmap factory options
final int REQUIRED_SIZE=70; //The new size we want to scale to (save big quantity of memory)
int scale=1; //we need to find the correct scale value. It should be the power of 2.
while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
scale*=2;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale; //decode with inSampleSize
selectedPhoto.setImageBitmap(BitmapFactory.decodeStream(new FileInputStream(standardImage), null, o2)); //assign the scaled image to the gridView
} catch (FileNotFoundException e) {
Log.i("Error","File not found");
}
selectedPhoto.getLayoutParams().height = 90; //use a fixed size for each thumnail
selectedPhoto.getLayoutParams().width = 90;
//TEXT VIEWS
TextView numberCopies = new TextView(this); //create new TextView
numberCopies.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT));
numberCopies.setGravity(Gravity.CENTER); //set position to the center in confront to the parent
numberCopies.setPadding(25, 25, 25, 25);
numberCopies.setTextColor(getResources().getColor(R.color.blackColor));
numberCopies.setText("2 copies "); //this need to be dynamic
RelativeLayout.LayoutParams layoutParamsNumberCopies = (RelativeLayout.LayoutParams) numberCopies.getLayoutParams();
layoutParamsNumberCopies.addRule(RelativeLayout.CENTER_HORIZONTAL); //add a rule to the layout params. We put his position at the horizontal center of the relative layout
numberCopies.setLayoutParams(layoutParamsNumberCopies); //set the layout rules to the textView
TextView priceCopies = new TextView(this);
priceCopies.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT));
priceCopies.setGravity(Gravity.CENTER);
numberCopies.setPadding(25, 25, 25, 25);
priceCopies.setTextColor(getResources().getColor(R.color.redColor));
RelativeLayout.LayoutParams layoutParamsPriceCopies = (RelativeLayout.LayoutParams) priceCopies.getLayoutParams();
layoutParamsPriceCopies.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
layoutParamsPriceCopies.addRule(RelativeLayout.CENTER_VERTICAL);
priceCopies.setLayoutParams(layoutParamsPriceCopies);
relativeLayout.addView(selectedPhoto);
relativeLayout.addView(numberCopies);
relativeLayout.addView(priceCopies);
linearLayout.addView(relativeLayout);
}
scrollView.addView(linearLayout);
setContentView(scrollView);
linearLayout.addView(relativeLayoutOpenButton); //add the button to the view
}
}
这是我尝试添加已添加到下一个活动的图像时收到的错误:
10-04 09:15:20.019: E/AndroidRuntime(1715): FATAL EXCEPTION: main
10-04 09:15:20.019: E/AndroidRuntime(1715): java.lang.RuntimeException: Unable to resume activity {com.example.dilandprints2/com.example.dilandprints2.PhotoManagement}: java.lang.StringIndexOutOfBoundsException: length=0; regionStart=0; regionLength=-1
10-04 09:15:20.019: E/AndroidRuntime(1715): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2742)
10-04 09:15:20.019: E/AndroidRuntime(1715): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771)
10-04 09:15:20.019: E/AndroidRuntime(1715): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235)
10-04 09:15:20.019: E/AndroidRuntime(1715): at android.app.ActivityThread.access$600(ActivityThread.java:141)
10-04 09:15:20.019: E/AndroidRuntime(1715): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
10-04 09:15:20.019: E/AndroidRuntime(1715): at android.os.Handler.dispatchMessage(Handler.java:99)
10-04 09:15:20.019: E/AndroidRuntime(1715): at android.os.Looper.loop(Looper.java:137)
10-04 09:15:20.019: E/AndroidRuntime(1715): at android.app.ActivityThread.main(ActivityThread.java:5041)
10-04 09:15:20.019: E/AndroidRuntime(1715): at java.lang.reflect.Method.invokeNative(Native Method)
10-04 09:15:20.019: E/AndroidRuntime(1715): at java.lang.reflect.Method.invoke(Method.java:511)
10-04 09:15:20.019: E/AndroidRuntime(1715): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
10-04 09:15:20.019: E/AndroidRuntime(1715): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
10-04 09:15:20.019: E/AndroidRuntime(1715): at dalvik.system.NativeStart.main(Native Method)
10-04 09:15:20.019: E/AndroidRuntime(1715): Caused by: java.lang.StringIndexOutOfBoundsException: length=0; regionStart=0; regionLength=-1
10-04 09:15:20.019: E/AndroidRuntime(1715): at java.lang.String.startEndAndLength(String.java:583)
10-04 09:15:20.019: E/AndroidRuntime(1715): at java.lang.String.substring(String.java:1464)
10-04 09:15:20.019: E/AndroidRuntime(1715): at com.example.dilandprints2.PhotoManagement.onResume(PhotoManagement.java:93)
10-04 09:15:20.019: E/AndroidRuntime(1715): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
10-04 09:15:20.019: E/AndroidRuntime(1715): at android.app.Activity.performResume(Activity.java:5182)
10-04 09:15:20.019: E/AndroidRuntime(1715): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732)
10-04 09:15:20.019: E/AndroidRuntime(1715): ... 12 more
请问有什么想法或建议吗?