Android GridView
is a view group which allows us to display items in a two dimensional grid.
How to create basic ListView
or GridView
you can read here.
In this tutorial you'll learn how to make material design android application using GridView
with header view and material ripple effect to show images from Download folder.
In this tutorial example project I have used android design support library and a material ripple library.
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.4.0' compile 'com.android.support:design:23.1.0' compile 'com.github.traex.rippleeffect:library:1.3' }
Add two items windowActionBar
and windowNoTitle
to styles.xml file.
<resources> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> ... <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> </style> </resources>
Open dimense.xml file from res/values and add dimen for app bar height.
<resources> ... <dimen name="app_bar_height">170dp</dimen> </resources>
Add new permission to AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Open your main XML layout file and add CoordinatorLayout
, AppBarLayout
, CollapsingToolbarLayout
, ImageView
, Toolbar
, NestedScrollView
, LinearLayout
and GridView
.
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/android_coordinator_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:id="@+id/appbar_layout" android:layout_width="match_parent" android:layout_height="@dimen/app_bar_height" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar_android_layout" android:layout_width="match_parent" android:layout_height="match_parent" app:expandedTitleGravity="bottom|center_horizontal" app:contentScrim="?attr/colorPrimary" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView android:id="@+id/image_view" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerInside" android:src="@android:drawable/ic_dialog_info" app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.7" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:id="@+id/nestedscrollview" android:layout_height="match_parent" android:fillViewport="true" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout android:id="@+id/linearLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <GridView android:id="@+id/grid" android:layout_width="wrap_content" android:layout_height="match_parent" android:columnWidth="200dp" android:gravity="center" android:listSelector="#00000000" android:numColumns="auto_fit" android:stretchMode="columnWidth" /> </LinearLayout> </android.support.v4.widget.NestedScrollView> </android.support.design.widget.CoordinatorLayout>
Create a new XML layout file called gridview_item.xml to make custom GridView
image and text design and add a LinearLayout
as root layout. Inside LinearLayout
add RippleView
with proper attribute like the below and inside RippleView
add ImageView
and TextView
in LinearLayout
.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/android_gridview_custom_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:padding="10dp"> <com.andexert.library.RippleView android:id="@+id/more" rv_centered="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" app:rv_color="#fff" app:rv_rippleDuration="200"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/linearLayout" android:orientation="vertical"> <ImageView android:id="@+id/gridview_image" android:layout_width="190dp" android:layout_height="150dp" android:src="@mipmap/ic_launcher" /> <TextView android:id="@+id/gridview_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/grid_image" android:layout_marginTop="10dp" android:gravity="center" android:text="Grid View Item" android:textColor="#444" android:textSize="12sp" android:textStyle="bold" /> </LinearLayout> </com.andexert.library.RippleView> </LinearLayout>
Following is the complete code of MainActivity.java file. In this activity, we will check for the SD Card existence and if exist will load images from Download folder. The image file paths and names from the SD Card are stored in an array and passed to the PhotoAdapter
to set it into the GridView
. On GridView
item click will show the name of image.
import android.os.Environment; import android.support.design.widget.CollapsingToolbarLayout; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.GridView; import android.widget.Toast; import java.io.File; public class MainActivity extends AppCompatActivity { Toolbar toolbar; CollapsingToolbarLayout toolbarLayout; GridView gridView; private File[] files; private String[] filesPaths; private String[] filesNames; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Check for SD Card if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { Toast.makeText(this, "Error! No SDCARD Found!", Toast.LENGTH_LONG).show(); } else { File dirDownload = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); if (dirDownload.isDirectory()) { files = dirDownload.listFiles(); filesPaths = new String[files.length]; filesNames = new String[files.length]; for (int i = 0; i < files.length; i++) { filesPaths[i] = files[i].getAbsolutePath(); filesNames[i] = files[i].getName(); } } } toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); toolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar_android_layout); toolbarLayout.setTitle("Photo gallery"); gridView = (GridView) findViewById(R.id.grid); gridView.setAdapter(new PhotoAdapter(this, filesNames, filesPaths)); gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(getApplicationContext(), filesNames[position], Toast.LENGTH_LONG).show(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_email: Toast.makeText(this, "EMail", Toast.LENGTH_LONG).show(); break; default: break; } return true; } }
Create a new java file with the name PhotoAdapter.java and extend it to BaseAdapter
. Following is the complete code of custom GridView
adapter file.
import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class PhotoAdapter extends BaseAdapter { private Context ctx; private final String[] filesNames; private final String[] filesPaths; public PhotoAdapter(Context ctx, String[] filesNames, String[] filesPaths) { this.ctx = ctx; this.filesNames = filesNames; this.filesPaths = filesPaths; } @Override public int getCount() { return filesNames.length; } @Override public Object getItem(int pos) { return pos; } @Override public long getItemId(int pos) { return pos; } @Override public View getView(int p, View convertView, ViewGroup parent) { View grid; LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); if (convertView == null) { grid = inflater.inflate(R.layout.gridview_item, null); TextView textView = (TextView) grid.findViewById(R.id.gridview_text); ImageView imageView = (ImageView)grid.findViewById(R.id.gridview_image); textView.setText(filesNames[p]); Bitmap bmp = BitmapFactory.decodeFile(filesPaths[p]); imageView.setImageBitmap(bmp); } else { grid = (View) convertView; } return grid; } }
Useful links