DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Low-Code Development: Leverage low and no code to streamline your workflow so that you can focus on higher priorities.

DZone Security Research: Tell us your top security strategies in 2024, influence our research, and enter for a chance to win $!

Launch your software development career: Dive head first into the SDLC and learn how to build high-quality software and teams.

Open Source Migration Practices and Patterns: Explore key traits of migrating open-source software and its impact on software development.

Related

  • How To Create a Homescreen Widget in Android
  • How Does WebView Actually Work on Android?
  • How To Integrate Chatbot With an Android App
  • Guide for Voice Search Integration to Your Flutter Streaming App

Trending

  • Leveraging Microsoft Graph API for Unified Data Access and Insights
  • Front-End Application Performance Monitoring (APM)
  • Performance and Scalability Analysis of Redis and Memcached
  • PostgreSQL BiDirectional Replication
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. Download and Display Image in Android GridView

Download and Display Image in Android GridView

By 
Nilanchala Panigrahy user avatar
Nilanchala Panigrahy
·
Jul. 06, 15 · Tutorial
Like (1)
Save
Tweet
Share
42.8K Views

Join the DZone community and get the full member experience.

Join For Free

This example is an improved version of my previous example Android GridView Example. Instead of using static images to display the grid items, let's make this example more realistic by downloading the data in real-time from the server and rendering the grid items. The following video depicts the output of this example.


Without wasting much time, let us jump straight into what it takes to build this kind of GridView. You need to follow the following steps to complete this example.

1. Add GridView in Activity Layout

First, create a new android project. For this example, I prefer to use Android Studio. Create a new layout file to your project res/layout folder and name it as activity_grid_view.xml. And add the following code blocks.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f0f0f0">

    <GridView
        android:id="@+id/gridView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:columnWidth="100dp"
        android:drawSelectorOnTop="true"
        android:gravity="center"
        android:numColumns="auto_fit"
        android:stretchMode="columnWidth"
        android:verticalSpacing="5dp"
        android:focusable="true"
        android:clickable="true"/>

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/progressBar"
        android:layout_centerInParent="true"
        android:visibility="gone"/>
</RelativeLayout>


The above layout is pretty straightforward. We have declared an GridView and a ProgressBar in activity layout. The progress bar will be displayed when the data is downloaded.

2. Declare GridView Item Layout

Let us now add another file named grid_item_layout.xml to res/layout folder. This layout will be used by a custom grid adapter for laying out individual grid items. For the sake of simplicity, we are adding an ImageView and a TextView.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="5dp"
    android:background="@drawable/grid_color_selector"
    android:orientation="vertical"
    android:padding="5dp">

    <ImageView
        android:id="@+id/grid_item_image"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:scaleType="centerCrop"/>

    <TextView
        android:id="@+id/grid_item_title"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:gravity="center"
        android:maxLines="2"
        android:ellipsize="marquee"
        android:textSize="12sp" />

</LinearLayout>


3. Adding Internet Permission

You might be aware that, the Android application must declare all the permissions that are required for the application. As we need to download the data from the server, we need to add  INTERNET permission. Add the following line to AndroidManifest.xml the file.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.javatechig.gridviewexample">

<uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name=".GridViewActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".DetailsActivity" />
    </application>

</manifest>


Notice that we have also declared all the activities used in the application.

4. Adding Picasso Image Downloading Library

Android open-source developer community brings some interesting libraries that can be integrated easily into Android applications. They serve a great deal of purpose and save a lot of time. Here in this example, I am talking about Picasso the image-loading library. We will add the Picasso library for downloading and caching images. Visit here to learn more about how to use the Picasso library on Android.

You can add the Picasso library by adding the following dependency to the build.gradle file.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.squareup.picasso:picasso:2.5.2'
}


5. Create a GridView Custom Adapter

A grid view is an adapter view. It requires an adapter to render the collection of data items. Add a new class named GridViewAdapter.java to your project and add the following code snippets.

package com.javatechig.gridviewexample;

import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;

public class GridViewAdapter extends ArrayAdapter<GridItem> {

    private Context mContext;
    private int layoutResourceId;
    private ArrayList<GridItem> mGridData = new ArrayList<GridItem>();

    public GridViewAdapter(Context mContext, int layoutResourceId, ArrayList<GridItem> mGridData) {
        super(mContext, layoutResourceId, mGridData);
        this.layoutResourceId = layoutResourceId;
        this.mContext = mContext;
        this.mGridData = mGridData;
    }


    /**
     * Updates grid data and refresh grid items.
     * @param mGridData
     */
    public void setGridData(ArrayList<GridItem> mGridData) {
        this.mGridData = mGridData;
        notifyDataSetChanged();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        ViewHolder holder;

        if (row == null) {
            LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, parent, false);
            holder = new ViewHolder();
            holder.titleTextView = (TextView) row.findViewById(R.id.grid_item_title);
            holder.imageView = (ImageView) row.findViewById(R.id.grid_item_image);
            row.setTag(holder);
        } else {
            holder = (ViewHolder) row.getTag();
        }

        GridItem item = mGridData.get(position);
        holder.titleTextView.setText(Html.fromHtml(item.getTitle()));

Picasso.with(mContext).load(item.getImage()).into(holder.imageView);
        return row;
    }

    static class ViewHolder {
        TextView titleTextView;
        ImageView imageView;
    }
}


Notice the following in the above code snippets,

  • The setGridData() method updates the data display on GridView.
  • The Picasso.with().load() the method is used to download the image from the URL and display it on the image view.
  • The GridViewAdapter class constructor requires the id of the grid item layout and the list of data to operate on.
  • You might be surprised, where the GridItem class came from. It's not magic, we need to add GridItem.java class to our project.  The GridItem class looks as follows.

6. Download Data and Hook it to the Activity

Now we will be heading towards hooking the adapter to GridView and making it functional. Create a new Java class and name it as GridViewActivity.java and perform the following steps.

  • Override the onCreate() method and set the layout by calling setContentView() method
  • Initialize the GridView and ProgressBar components by using their declared layout id.
  • Initialize the CustomGridView adapter bypassing the grid row layout id and the list of GridItem objects.
  • Use AsyncTask to download data from the server, once the download is successful read the stream JSON response.
  • Parse the JSON string into the list of GridItem objects. Once downloading and parsing is completed, in onPostExecute() callback update the UI elements.

The following code does all the above steps as described. Add the following code to GridViewActivity class.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ProgressBar;
import android.widget.Toast;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class GridViewActivity extends ActionBarActivity {
    private static final String TAG = GridViewActivity.class.getSimpleName();
    private GridView mGridView;
    private ProgressBar mProgressBar;
    private GridViewAdapter mGridAdapter;
    private ArrayList<GridItem> mGridData;
    private String FEED_URL = "http://javatechig.com/?json=get_recent_posts&count=45";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gridview);

        mGridView = (GridView) findViewById(R.id.gridView);
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);

        //Initialize with empty data
        mGridData = new ArrayList<>();
        mGridAdapter = new GridViewAdapter(this, R.layout.grid_item_layout, mGridData);
        mGridView.setAdapter(mGridAdapter);

        //Start download
        new AsyncHttpTask().execute(FEED_URL);
        mProgressBar.setVisibility(View.VISIBLE);
    }

    //Downloading data asynchronously
    public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {

        @Override
        protected Integer doInBackground(String... params) {
            Integer result = 0;
            try {
                // Create Apache HttpClient
                HttpClient httpclient = new DefaultHttpClient();
                HttpResponse httpResponse = httpclient.execute(new HttpGet(params[0]));
                int statusCode = httpResponse.getStatusLine().getStatusCode();

                // 200 represents HTTP OK
                if (statusCode == 200) {
                    String response = streamToString(httpResponse.getEntity().getContent());
                    parseResult(response);
                    result = 1; // Successful
                } else {
                    result = 0; //"Failed
                }
            } catch (Exception e) {
                Log.d(TAG, e.getLocalizedMessage());
            }
            return result;
        }

        @Override
        protected void onPostExecute(Integer result) {
            // Download complete. Let us update UI
            if (result == 1) {
                mGridAdapter.setGridData(mGridData);
            } else {
                Toast.makeText(GridViewActivity.this, "Failed to fetch data!", Toast.LENGTH_SHORT).show();
            }
            mProgressBar.setVisibility(View.GONE);
        }
    }

    String streamToString(InputStream stream) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream));
        String line;
        String result = "";
        while ((line = bufferedReader.readLine()) != null) {
            result += line;
        }

        // Close stream
        if (null != stream) {
            stream.close();
        }
        return result;
    }

    /**
     * Parsing the feed results and get the list
     * @param result
     */
    private void parseResult(String result) {
        try {
            JSONObject response = new JSONObject(result);
            JSONArray posts = response.optJSONArray("posts");
            GridItem item;
            for (int i = 0; i < posts.length(); i++) {
                JSONObject post = posts.optJSONObject(i);
                String title = post.optString("title");
                item = new GridItem();
                item.setTitle(title);
                JSONArray attachments = post.getJSONArray("attachments");
                if (null != attachments && attachments.length() > 0) {
                    JSONObject attachment = attachments.getJSONObject(0);
                    if (attachment != null)
                        item.setImage(attachment.getString("url"));
                }
                mGridData.add(item);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}


At this point, you will be able to run the app and notice that the app will download the data from the server and display it on GridView.

7. Handle GridView Click Event

Right now GridView is not responding to user clicks. Let us make it more functional by adding the following code.

mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {

//Get item at position
GridItem item = (GridItem) parent.getItemAtPosition(position);

//Pass the image title and url to DetailsActivity
                Intent intent = new Intent(GridViewActivity.this, DetailsActivity.class);
                intent.putExtra("title", item.getTitle());
                intent.putExtra("image", item.getImage());

//Start details activity
startActivity(intent);
}
});


When a user clicks on a grid item, we will start another activity that displays the full-screen image. You can start one activity from another by calling startActivity() method.

We need to pass the details of the item such as the title, and image URL for displaying it on DetailsActivity.

8. Create Details Activity Layout

Add a new layout file to res/layout directory, and name it as activity_details_view.xml and add the following code snippets.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/grid_item_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:scaleType="fitCenter" />

    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:background="#00000c"
        android:padding="10dp"
        android:textColor="#fff"
        android:textSize="20dp" />
</FrameLayout>


9. Completing the Details Activity

The DetailsActivity retrieves the details passed from GridViewActivity and renders the details on the screen. Create a new class named DetailsActivity and add the following code snippets.

package com.javatechig.gridviewexample;

import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.text.Html;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;

public class DetailsActivity extends ActionBarActivity {
    private TextView titleTextView;
    private ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_details_view);

        ActionBar actionBar = getSupportActionBar();
        actionBar.hide();

        String title = getIntent().getStringExtra("title");
        String image = getIntent().getStringExtra("image");
        titleTextView = (TextView) findViewById(R.id.title);
        imageView = (ImageView) findViewById(R.id.grid_item_image);
        titleTextView.setText(Html.fromHtml(title));

        Picasso.with(this).load(image).into(imageView);
    }
}


10. Download the Complete Example

Download from GitHub.

11. Custom Activity Transition in GridView

Continue reading in our next tutorial.

Download Android (robot)

Published at DZone with permission of Nilanchala Panigrahy, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How To Create a Homescreen Widget in Android
  • How Does WebView Actually Work on Android?
  • How To Integrate Chatbot With an Android App
  • Guide for Voice Search Integration to Your Flutter Streaming App

Partner Resources


Comments

ABOUT US

  • About DZone
  • Send feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: