0

I want to set my gridview to have cells of a squared size of screen width / number of rows. I'm having issues with the images I'm pulling down from the net. I can hard code it in the XML and it will all work, but then I need dimens for every layout size. There is two image views, one is to have a background tile if the image itself isn't square. I can't seem to find how to set it dynamically in code.. I've tried to set min height and with, tried setting the layouts to fill parent then setting the size of the image view at inflation. Either its the right size from the start or it fails, it seems..

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gridview_parent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="@dimen/element_spacing"
android:paddingTop="@dimen/element_spacing"
android:layout_centerHorizontal="true"
>


<ImageView
    android:id="@+id/gridview_adapter_background_iv"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_margin="@dimen/element_spacing"
    android:background="@color/color_primary"
    android:contentDescription="@string/content_description_ui"
    />

<ImageView
    android:id="@+id/gridview_adapter_iv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/element_spacing"
    android:layout_centerInParent="true"
    android:contentDescription="@string/content_description_result"
    />


<ProgressBar
    android:id="@+id/grid_adapter_spinner"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true" />


</RelativeLayout>

the get view..

@Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        final ImageDataViewHolder imageDataViewHolder;

        /*
         * see if we need to inflate the view, or if we can make use of the view holder pattern
         */
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.adapter_gridview, parent, false);
            imageDataViewHolder = new ImageDataViewHolder();
            imageDataViewHolder.gridview_adapter_iv = (ImageView) convertView.findViewById(R.id.gridview_adapter_iv);
            imageDataViewHolder.gridview_adapter_background_iv = (ImageView) convertView.findViewById(R.id.gridview_adapter_background_iv);


            imageDataViewHolder.grid_adapter_spinner = (ProgressBar) convertView.findViewById(R.id.grid_adapter_spinner);
        } else {
            imageDataViewHolder = (ImageDataViewHolder) convertView.getTag();
        }

        /*
         * Set the UI elements, reset the spinner
         */


        imageDataViewHolder.position = position;
        imageDataViewHolder.grid_adapter_spinner.setVisibility(View.VISIBLE);

        final String url = mValues.get(position).getUrl();

        imageDataViewHolder.gridview_adapter_iv.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                mCallbacks.click(url);
            }

        });

        convertView.setTag(imageDataViewHolder);

        /*
         * Process the bitmap. If it exists, set it. If not, create a volley request to try to access
         * it. If it succeeds, save the bitmap to the cache. If it fails put up error icon.
         */
        Bitmap bm = mCache.get(url);
        if (bm != null) {
            imageDataViewHolder.gridview_adapter_iv.setImageBitmap(bm);
            imageDataViewHolder.grid_adapter_spinner.setVisibility(View.INVISIBLE);
        } else {
            imageDataViewHolder.gridview_adapter_iv.setImageBitmap(null);
            ImageRequest imageRequest = new ImageRequest(url, new Response.Listener<Bitmap>() {

                @Override
                public void onResponse(Bitmap response) {
                    mCache.put(url, response);
                    /*
                     * Check to make sure its the same view is visible before making edits.
                     * Else we will get a flicker effect as different images are downloaded.
                     *
                     */
                    if (imageDataViewHolder.position == position) {
                        imageDataViewHolder.gridview_adapter_iv.setImageBitmap(response);
                        imageDataViewHolder.grid_adapter_spinner.setVisibility(View.INVISIBLE);
                    }
                }

            }, mSize, mSize, null, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                    imageDataViewHolder.grid_adapter_spinner.setVisibility(View.INVISIBLE);
                    imageDataViewHolder.gridview_adapter_iv.setImageResource(R.drawable.ic_error_outline_white_24dp);
                }
            });
            mVolleySingleton.addRequest(imageRequest);
        }
        return convertView;
    }
StarWind0
  • 1,554
  • 2
  • 17
  • 46
  • Go with below solution or consider this: http://stackoverflow.com/questions/29956014/why-should-we-use-xml-layouts – Nanoc Nov 11 '15 at 14:19
  • This is where I wonder if I am aproaching this wrong. Would it kill me to just add the different layouts? The problem I have is that I don't have more than 2 screens to try it with.. – StarWind0 Nov 13 '15 at 05:27
  • You can use the emulator with every screen you want. – Nanoc Nov 13 '15 at 08:45
  • I have learned from experience that the emulator is never to be used in place of real devices.. but I get what you're saying. – StarWind0 Nov 14 '15 at 09:22
  • I decided that I should do it the correct way and create 5 different dimens files. Using the Sdp (not sw). Then I set the height of each grid item to 1/2 SW. I download the image at max size of 1/2 screen size ^2. Trying to make it dynamic programmatically and scaling just isn't a good idea for gridview paired with remote data. I also made the background imageview larger than screensize in terms of width to prevent it from having inconsistent spacing, the scaling of the gridview reduces it to the correct width. – StarWind0 Nov 14 '15 at 09:28
  • Have fun creating xml files. – Nanoc Nov 16 '15 at 08:48
  • It took me like 4 minutes. – StarWind0 Nov 17 '15 at 23:06

1 Answers1

0

Your best bet is to subclass RelativeLayout and override onMeasure():

public class SquareRelativeLayout extends RelativeLayout{

    public SquareRelativeLayout (Context context) {
        super(context);
    }

    public SquareRelativeLayout (Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public SquareRelativeLayout (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
    }

}

This should work for GridView as it will use a mode of MeasureSpec.EXACTLY, IIRC. If it doesn't work, you can tweak the code using suggestions from here: Simple way to do dynamic but square layout

BTW, You should be able to use a single ImageView by setting the background and then specifying android:scaleType="fitCenter" for the bitmap.

Community
  • 1
  • 1
kris larson
  • 30,387
  • 5
  • 62
  • 74