0

I'm developing an application where I load several Buttons in a GridView.

<?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="fill_parent"
      android:paddingLeft="25dp"
      android:paddingRight="25dp"
      android:paddingTop="5dp"
      android:paddingBottom="5dp"
      android:layout_height="wrap_content"
      android:gravity="center"
      android:orientation="vertical">
    <GridView
        android:id="@+id/gridview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:columnWidth="128dp"
        android:numColumns="auto_fit"
        android:verticalSpacing="5dp"
        android:horizontalSpacing="5dp"
        android:stretchMode="columnWidth"
        android:gravity="center" />
  </LinearLayout>

The buttons are dynamically added with an Adapter, but I cannot scale or auto fit the images as I would like to, if I predefined the boundaries (320x320) in some devices look great in other ones too small or too big and if I choose the Intrinsic boundaries they are always miniature.

Predefined boundaries (320x320):

Smartphone view:

enter image description here

Tablet view:

enter image description here

Intrinsic boundaries (136x136):

enter image description here

I'm storing the images in the Assets directory, your first question is why?

You could tell me me that I should save them in the Resources/drawable and I'm aware of it, but I have more than 100 images and each of them are stored in a sub-folders with a unique IDs, which can contains at least one image with an ID like this one: 1.jpg, 2.jpg, etc.

As you can appreciate if I move all those images and sub-directories to the drawable folder, it just not going to work (Can the Android drawable directory contain subdirectories?).

I have this function in order to get the Drawable from the Assets folder:

public Drawable GetImage(int ID)
{
    var thumbnail = string.Format("Thumbnails/{0}/1.jpg", ID);
    using (StreamReader sr = new StreamReader(Application.Context.Assets.Open(thumbnail)))
    {
        Drawable d = Drawable.CreateFromStream(sr.BaseStream, null);

        d.SetBounds(0, 0, 320, 320);

        return d;
    }
}

Here is how I load the data in the Adapter to the Buttons:

btnRecipe.Text = data[position].name;
btnRecipe.SetHeight(560);
//            btnRecipe.SetWidth(122);
// btnRecipe.SetCompoundDrawablesWithIntrinsicBounds();
btnRecipe.SetTextColor(new Android.Graphics.Color(255, 255, 255));
btnRecipe.SetCompoundDrawables(null, data[position].image, null, null);

I'd like to know if there is any way to deal or Auto Fit the images because I have another example that with data from the Drawable folder and XML code the image is scaled without anything else for example:

enter image description here

Code:

<Button
    android:text="@string/BtnComidas"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="@color/my_white"
    android:id="@+id/BtnComidas"
    android:drawableTop="@drawable/comidas" />

Also, I'd like to clarify that this image is smaller 128x128 than the previous ones (136x136), furthermore, it looks much better and I have just one copy of the image in the Drawable folder, I don't have a hdpi or a mdpi copies and as you can see it looks great in smartphones and tablets, I didn't need to do any additional change in order to scale it.

A possible questions and answer, why am I using a GridView in order to load the buttons? If I should use another control or Layout, for instance.

I didn't know another way in order to display an image and text at the same time and I was able to handle the click event as I expected.

Besides, I'm open to any suggestion if someone has another approach of how displaying several images with text in a GridView or something else that could solve my current problem. Thanks for your help, time, experience and worthy knowledge.

Federico Navarrete
  • 3,069
  • 5
  • 41
  • 76

1 Answers1

0

I was able to find a solution to my problem that could help more people too:

1) You need to share the Column Width of your GridView to the constructor:

GridDishes.Adapter = new GridViewAdapter(this, data, GridDishes.ColumnWidth, IsSmartphone());

2) Then you configure the ideal size:

public GridViewAdapter(Context c, List<CompatedInfo> data, int size, bool isSmartphone)
{
    NotifyDataSetChanged();
    context = c;
    this.data = data;

    //Define the size that you're going to use
    if (Size > 0)
        Size = (int)(size * 0.8);

    //This is going to help you to have the same size for all elements
    if (isSmartphone)
        Height = (int)(Size * 1.65);
    else
        Height = (int)(Size * 1.7);
}

3) Define the new size in the adapter:

data[position].image.SetBounds(0, 0, Size, Size);

4) If you want that all views have the same Height, the height is predefined in the Constructor:

btnRecipe.SetHeight(Height);

Optional:

This function is useful if you want to determinate the screen and do some small changes as I did with the maximum size for the elements:

private bool IsSmartphone()
{
    DisplayMetrics metrics = new DisplayMetrics();
    WindowManager.DefaultDisplay.GetMetrics(metrics);

    float yInches = metrics.HeightPixels / metrics.Ydpi;
    float xInches = metrics.WidthPixels / metrics.Xdpi;
    double diagonalInches = Math.Sqrt(xInches * xInches + yInches * yInches);

    if (diagonalInches >= 6.5)
    {
        return false;
    }
    else
    {
        return true;
    }
}

Source of the function:

https://stackoverflow.com/a/24701063/2889347

Community
  • 1
  • 1
Federico Navarrete
  • 3,069
  • 5
  • 41
  • 76