I'm having a problem of displaying ImageViews with the correct size. Almost all the posts that I've read through involves ImageViews that are created in the layout file. However in my case, I'm creating ImageViews programmatically.
I'm trying to display all images from a particular folder located in the storage. The bitmaps retrieved will be placed in ImageViews which are contained within a GridView.
Here's my code:
//pass an array containing all images paths to adapter
imageGrid.setAdapter(new GridViewAdapter(getActivity(), FilePathStrings));
part of GridVewAdapter code:
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if(convertView == null){
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setPadding(5, 5, 5, 5);
imageView.setAdjustViewBounds(true);
}else{
imageView = (ImageView) convertView;
}
imageView.setTag(filepath[position]);
new LoadImages(imageView).execute();
return imageView;
}
AsyncTask to retrieve bitmaps:
private class LoadImages extends AsyncTask<Object, Void, Bitmap> {
private ImageView imgView;
private String path;
private LoadImages(ImageView imgView) {
this.imgView = imgView;
this.path = imgView.getTag().toString();
}
#Override
protected Bitmap doInBackground(Object... params) {
Bitmap bitmap = null;
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = 6;
bitmap = BitmapFactory.decodeFile(path, bmOptions);
try {
int dimension = getSquareCropDimensionForBitmap(bitmap);
bitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension);
}catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
if (!imgView.getTag().toString().equals(path)) {
return;
}
if(result != null && imgView != null){
imgView.setVisibility(View.VISIBLE);
imgView.setImageBitmap(result);
}else{
imgView.setVisibility(View.GONE);
}
}
}
Method to get equal dimensions so bitmaps will be displayed as squares:
private int getSquareCropDimensionForBitmap(Bitmap bitmap) {
int dimension;
//If the bitmap is wider than it is height then use the height as the square crop dimension
if (bitmap.getWidth() >= bitmap.getHeight()) {
dimension = bitmap.getHeight();
}
//If the bitmap is taller than it is width use the width as the square crop dimension
else {
dimension = bitmap.getWidth();
}
return dimension;
}
GridView in the layout file:
<GridView
android:id="#+id/imageGridView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnWidth="30dp"
android:numColumns="5"
android:verticalSpacing="5dp"
android:horizontalSpacing="5dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:layout_marginTop="30dp">
</GridView>
The result that I've gotten:
The circled thin "lines" are actually the ImageViews displayed.
Any help is very much appreciated. Thank you in advance!
<GridView
android:id="#+id/imageGridView"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:numColumns="auto_fit"
android:verticalSpacing="5dp"
android:horizontalSpacing="5dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:layout_marginTop="30dp">
I have other views above the GridView so I can't set its height to fill_parent/match_parent in the .xml file as it will affect the views above.
The solution to my problem is to set GridView's height and width programmatically.
Replace:
imageView.setLayoutParams(new GridView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
With this:
imageView.setLayoutParams(new GridView.LayoutParams(int height, int width));
Explanation:
Grid View doc
Anyone who has a better answer, please post it :)
Related
I am trying to set a 3:2 ratio for a gridview (IE 300 pixels by 200 per cell). Here is my image adapter:
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
// if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(200, 200));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
// references to our images
private Integer[] mThumbIds = {
R.drawable.image1, R.drawable.image2, R.drawable.image3,
};
}
I've tried adjusting the imageView.setLayoutParams(new GridView.LayoutParams(200, 200)); width parameter to 300 but it results in overlapping. Here is my XML File:
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"
/>
Weird overlapping:
Hi there you can try like this from your Activity :
ViewGroup.LayoutParams layoutParams = gridview.getLayoutParams();
layoutParams.height = 200;
layoutParams.width = 300;
gridview.setLayoutParams(layoutParams);
or
int final width = 300;
int final height = 200;
ViewGroup.LayoutParams lauoutParams = new ViewGroup.LayoutParams(width,height);
gridView.setLayoutParams(lp);
This might help.
Discovered this library: AsymetricGridView
The first image is being overlapped by the second image in the grid. I want first image to be bigger than other images.First image should match the width of the device screen.
This is my xml
<GridView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/grid"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:numColumns="auto_fit"
android:columnWidth="90dp"
android:horizontalSpacing="10dp"
android:verticalSpacing="10dp"
android:gravity="center"
android:stretchMode="columnWidth"
android:paddingTop="16dp"
/>
This is my imageadapter code
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
MainActivity mainActivity=new MainActivity();
WindowManager wm = (WindowManager) mContext
.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int imgSize = 0;
if (convertView == null) {
// if it's not recycled, initialize some attributes
if(position!=0)
{
imgSize=200;
}
else
{
imgSize=size.x;
}
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(imgSize, 200));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
Screen Shot of Second image overlapping the first one
I have a GridView where I add images directly with ImageView (I don't use an XML for the image). Now, I want to add image name at the bottom of each cell using a TextView. How can I do it? Thanks in advance.
Custom Adapter Class:
public class GridViewImageAdapter extends BaseAdapter {
private Activity _activity;
private ArrayList<String> _filePaths = new ArrayList<String>();
private int imageWidth;
private GridView imageCarrete;
public GridViewImageAdapter(Activity activity, ArrayList<String> filePaths,
int imageWidth, GridView imageCarrete) {
this._activity = activity;
this._filePaths = filePaths;
this.imageWidth = imageWidth;
this.imageCarrete = imageCarrete;
}
#Override
public int getCount() {
return this._filePaths.size();
}
#Override
public Object getItem(int position) {
return this._filePaths.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(_activity);
} else {
imageView = (ImageView) convertView;
}
// get screen dimensions
Bitmap image = decodeFile(_filePaths.get(position), imageWidth,
imageWidth);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new GridView.LayoutParams(imageWidth,
imageWidth));
imageView.setImageBitmap(image);
// Listener del GridView
imageCarrete.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
Intent i = new Intent(_activity, FullScreenViewActivity.class);
i.putExtra("position", position);
_activity.startActivityForResult(i, 1234);
}
});
return imageView;
}
/*
* Resizing image size
*/
public static Bitmap decodeFile(String filePath, int WIDTH, int HIGHT) {
try {
File f = new File(filePath);
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
final int REQUIRED_WIDTH = WIDTH;
final int REQUIRED_HIGHT = HIGHT;
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_WIDTH
&& o.outHeight / scale / 2 >= REQUIRED_HIGHT)
scale *= 2;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
public void remove(String path){
_filePaths.remove(path);
}
}
GridView XML
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/grid_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:numColumns="auto_fit"
android:gravity="center"
android:stretchMode="columnWidth"
android:background="#000000">
</GridView>
Within your getView() method, replace your ImageView with a TextView with a drawable:
TextView tv = new TextView(context);
tv.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
you will supply the drawable to the top and 0 to the rest, ie:
tv.setCompoundDrawablesWithIntrinsicBounds(0, yourDrawable, 0, 0);
Just create a LinearLayout as you are creating Imagview in getView() method... add ImageView and TextView to it with addView() method.... have a look ..
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout _ll;
if (convertView == null) {
_ll = new LinearLayout(mContext);
_ll.setOrientation(LinearLayout.VERTICAL);
ImageView img = new ImageView(mContext);
img.setLayoutParams(new LinearLayout.LayoutParams(100, 100)); // your image size
img.setBackgroundResource(images[position]); // here pass your array list position
_ll.addView(img);
TextView text = new TextView(mContext);
text.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
text.setText("dsaf");
text.setGravity(Gravity.CENTER);
_ll.addView(text);
} else {
_ll = (LinearLayout) convertView;
}
return _ll;
}
You can also use RelativeLayout if you want to overlay your text over image..
My application is something that is having some categories, I am showing these categories in a grid view,I was successful in doing that.However later, I felt that I have a need to show notifications for each of the categories like the following:
I was thinking that I will have to take a hidden view component for the notification count for each category, that I will need to show up only whenever there is a notification received regarding that category.But the thing is that it may happen that I may be receiving notifications of various categories simultaneously and hence I will need to call notifyDataSetChanged(),(dont know my approach is right or not) each time to show up the notification count.(which may be a costlier process)
I want to know that how can I implement this gridview with notifications functionality efficiently, What if I want that the notification pops up with some animation, like the second bubble in the image,(and how to do that).
Framelayout in GridView seems to be the solution but it will be best if some example similar to that is shown to me.
I am also unsure about the approach I am thinking of.Is it a valid approach or some alternatives are there.
Here is my GridView:
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:layout_marginTop="5dp"
android:verticalSpacing="2dp"
android:horizontalSpacing="2dp"
android:scrollingCache="true"
android:smoothScrollbar="true"
android:clipChildren="true"
android:alwaysDrawnWithCache="true"
android:numColumns="auto_fit"
android:columnWidth="100dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:background="#000000">
</GridView>
The Adapter class:
class ImageAdapterTabView extends BaseAdapter {
private Context context;
ArrayList<String> imageList = new ArrayList<String>();
public ImageAdapterTabView(Context c) {
context = c;
}
void add(String path){
imageList.add(path);
}
#Override
public int getCount() {
return imageList.size();
}
#Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(context);
imageView.setLayoutParams(new GridView.LayoutParams(350, 350));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setAdjustViewBounds(true);
// imageView.setPadding(5, 5, 5, 5);
} else {
imageView = (ImageView) convertView;
}
Bitmap bm = decodeSampledBitmapFromUri(imageList.get(position), 100, 100);
imageView.setImageBitmap(bm);
return imageView;
}
public Bitmap decodeSampledBitmapFromUri(String path, int reqWidth, int reqHeight) {
Bitmap bm = null;
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(path, options);
return bm;
}
public int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float)height / (float)reqHeight);
} else {
inSampleSize = Math.round((float)width / (float)reqWidth);
}
}
return inSampleSize;
}
}
you should have to do following step
create layout for grid item
take relative layount with image and textview(top corner)
also create custom list
now you have to change as per item visibility of textview hide and show
Register each view as observer for the event..When the event happens you can show the notification.You would not need to do notifyDataSetChanged() everytime.However be careful of not leaking view objects.
To learn more about observe pattern refer-https://en.wikipedia.org/wiki/Observer_pattern
I am able to manage the horizontal space between images in a grid view. But how to reduce vertical space between images in a grid view.
Following is my code:
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:layout_margin="5dp">
<GridView
android:id="#+id/gridView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="0dp"
android:verticalSpacing="5dp"
android:horizontalSpacing="5dp"
android:scrollingCache="true"
android:smoothScrollbar="true"
android:clipChildren="true"
android:alwaysDrawnWithCache="true"
android:numColumns="auto_fit"
android:columnWidth="70dp">
</GridView>
</LinearLayout>
getView method
//---returns an ImageView view---
public View getView(int position, View convertView, ViewGroup parent)
{
ImageView imageView = null;
if (convertView == null) {
imageView = new ImageView(context);
imageView.setLayoutParams(new GridView.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
imageView.setTag(position);
} else {
imageView = (ImageView) convertView;
}
if((Integer)imageView.getTag() == 0) {
Bitmap bitmap = Bitmap.createScaledBitmap(imgPic.get(position).getBitmap(), 250, 200, false);
imageView.setImageBitmap(bitmap);
}else {
FileInputStream fs = null;
//Bitmap bm;
try {
fs = new FileInputStream(new File(imgPic.get(position).getFilePath().toString()));
if(fs!=null) {
//to get the thumbnail view of the image
Bitmap scaledBitmap = decodeFile(imgPic.get(position).getFilePath().toString(), 250, 200);
imageView.setImageBitmap(scaledBitmap);
imageView.setId(position);
}
} catch (IOException e) {
e.printStackTrace();
} finally{
if(fs!=null) {
try {
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return imageView;
}
decodeFile is a function to resize the image
You use the attribute android:horizontalSpacing="5dp", decreased its value.