Android
GridView

[Android]GridViewでページぐるぐる

More than 3 years have passed since last update.

開発環境

AndroidStudio

Volleyを使えるようにしておく

サーバ側との通信を手軽に実装できるモジュールを追加し使えるようにしておく

InstagramのAPIを使えるようにしておく

https://instagram.com/developer/#

新規作成・編集するファイル

(1)BitmapLruCache.java
イメージキャッシュを取り扱う
(2)Instagram.java
JSONから取得したデータを格納(set)、取り出す(get)するデータオブジェクトクラス
(3)MainActivity.java
(4)MyAdapter.java
グリッドビューに情報を提供するアダプタークラス
(5)MyVolley.java
Volley関連
(6)SingleTonVolley.java
Volleyのリクエストをシングルトンで扱うため
http://www.vagrantup.jp/entry/2013/12/07/164310

(7)activity_main.xml
(8)item.xml
グリッドビューの1グリッドのレイアウト
(9)ids.xml
ViewHolderにつけるIDの定義

(10)AndroidManifest.xml
サーバとの通信を許可する定義と、Volleyをシングルトンで使用する定義を追加する

とりあえず動くレベルの実装。
とりあえず外堀から実装

BitmapLruCache

public class BitmapLruCache extends LruCache<String,Bitmap> implements ImageLoader.ImageCache {

    public BitmapLruCache(int maxSize) {
        super(maxSize);
    }

    @Override
    public Bitmap getBitmap(String url) {
        return get(url);
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        put(url,bitmap);
    }
    public int sizeOf(String key, Bitmap value){
        return value.getRowBytes() * value.getHeight();
    }
}

Instagram

public class Instagram {

    private String caption;
    private String imgUrl;
    private int likes;
    private int cmtCnt;

    public String getCaption(){
        return this.caption;
    }
    public void setCaption(String set_caption){
        this.caption = set_caption;
    }

    public String getImgUrl(){
        return this.imgUrl;
    }
    public void setImgUrl(String set_imgUrl){
        this.imgUrl = set_imgUrl;
    }

    public int getLikes(){
        return likes;
    }
    public void setLikes(int set_likes){
        this.likes = set_likes;
    }
    public int getCmtCnt(){
        return cmtCnt;
    }
    public void setCmtCnt(int set_cmtCnt){
        this.cmtCnt = set_cmtCnt;
    }
}

SingleTonVolley

public class SingleTonVolley extends Application {

    public void onCreate(){
        super.onCreate();
        init();
    }
    private void init() {
        MyVolley.init(this);
    }

}

MyVolley

public class MyVolley {

    private static RequestQueue mRequestQueue;
    private static ImageLoader mImageLoader;

    public MyVolley(){

    }

    public static void init(Context context){
        mRequestQueue = Volley.newRequestQueue(context);
        int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
        int cacheSize = 1024*1024*memClass / 8;
        mImageLoader = new ImageLoader(mRequestQueue, new BitmapLruCache(cacheSize));
    }

    public static RequestQueue getRuequestQueue(){
        if(mRequestQueue != null){
            return mRequestQueue;
        }
        else{
            throw new IllegalStateException("RequestQueue not initialized");
        }
    }
    public static ImageLoader getImageLoader(){
        if(mImageLoader != null){
            return mImageLoader;
        }
        else{
            throw new IllegalStateException("ImageLoader not initialized");
        }
    }
}

AndroidManifest.xml

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

layout/item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:padding="5dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/iv_thumb"
        android:layout_width="match_parent"
        android:layout_height="200dp" />


    <LinearLayout
        android:padding="3dp"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
            android:src="@drawable/thumbsup"
            android:layout_width="20dp"
            android:layout_height="20dp" />

        <TextView
            android:id="@+id/likes"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <ImageView
            android:src="@drawable/comment"
            android:layout_width="20dp"
            android:layout_height="20dp" />

        <TextView
            android:id="@+id/cmtCnt"
            android:paddingRight="10dp"
            android:paddingLeft="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:paddingTop="2dp"
        android:background="#000000"/>

</LinearLayout>

values/ids.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="id_holder" type="id"/>
</resources>

MyAdapter

public class MyAdapter extends ArrayAdapter<Instagram> {

    private final ImageLoader mImageLoader;

    public MyAdapter(Context context, int resource, List<Instagram> objects, ImageLoader imageLoader) {
        super(context, resource, objects);
        mImageLoader = imageLoader;
    }

    public View getView(int position, View convertView, ViewGroup parent){
        View v = convertView;
        if(v==null){
            LayoutInflater vi = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.item, null);
        }
        ViewHolder holder = (ViewHolder)v.getTag(R.id.id_holder);

        if(holder==null){
            holder = new ViewHolder(v);
            v.setTag(R.id.id_holder, holder);
        }
        Instagram instagrams = getItem(position);
        if(instagrams.getImgUrl() != null){
            holder.image.setImageUrl(instagrams.getImgUrl(), mImageLoader);
        }

        holder.likes.setText(String.valueOf(instagrams.getLikes()));
        holder.cmtCnt.setText(String.valueOf(instagrams.getCmtCnt()));
        return v;

    }


    private class ViewHolder {

        NetworkImageView image;
        TextView likes;
        TextView cmtCnt;

        public ViewHolder(View v){
            image = (NetworkImageView)v.findViewById(R.id.iv_thumb);
            likes = (TextView)v.findViewById(R.id.likes);
            cmtCnt = (TextView)v.findViewById(R.id.cmtCnt);
            v.setTag(this);
        }
    }

}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#ffffff"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <GridView
        android:id="@+id/gridview1"
        android:numColumns="auto_fit"
        android:verticalSpacing="10dp"
        android:horizontalSpacing="10dp"
        android:stretchMode="columnWidth"
        android:gravity="center"
        android:layout_weight="1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

    </GridView>

    <ProgressBar
        android:id="@+id/pd"
        android:layout_gravity="center"
        android:background="#a0909090"
        style="?android:attr/progressBarStyleSmall"
        android:layout_width="fill_parent"
        android:layout_height="30dp" />

</LinearLayout>

MainActivity

public class MainActivity extends Activity {


    private GridView mGridView;
    private ArrayList<Instagram>mEntries = new ArrayList<Instagram>();
    private String apiUrl = "https://api.instagram.com/v1/tags/[検索ワード]/media/recent?client_id=[client_id]&count=20";
    private String nextMaxId;
    private MyAdapter mAdapter;
    private boolean mHasData = false;
    private boolean mInError = false;
    private ProgressBar pd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mGridView = (GridView)findViewById(R.id.gridview1);

        mAdapter = new MyAdapter(this, 0, mEntries, MyVolley.getImageLoader());
        mGridView.setAdapter(mAdapter);
        mGridView.setOnScrollListener(new EndlessScrollListener());
    }

    @Override
    protected void onResume(){
        super.onResume();
        if(!mHasData && !mInError){
            loadPage();
        }
    }

    private void loadPage() {
        RequestQueue queue = MyVolley.getRuequestQueue();
        apiUrl = apiUrl + "&max_tag_id=" + this.nextMaxId;
        JsonObjectRequest mReq = new JsonObjectRequest(
                Request.Method.GET,
                apiUrl,
                null,
                createMyReqSuccessListener(),
                createMyReqErrorListener()
        );
        queue.add(mReq);
    }

    private Response.ErrorListener createMyReqErrorListener() {
        return null;
    }

    private Response.Listener<JSONObject> createMyReqSuccessListener() {
        return new Response.Listener<JSONObject>(){

            @Override
            public void onResponse(JSONObject response) {

                try {
                    nextMaxId = response.getJSONObject("pagination").getString("next_max_id");
                    JSONArray arr = response.getJSONArray("data");

                    for(int i=0; i<arr.length(); i++){
                        JSONObject json = arr.getJSONObject(i);
                        String text = null;
                        Instagram itg = new Instagram();

                        //キャプションセット
/*
                        JSONObject caption = json.getJSONObject("caption");
                        itg.setCaption(caption.getString("text"));
*/
                        //画像セット
                        String imgUrl = json.getJSONObject("images").getJSONObject("standard_resolution").getString("url");
                        itg.setImgUrl(imgUrl);

                        //like情報の表示
                        int likes = json.getJSONObject("likes").getInt("count");
                        itg.setLikes(likes);

                        //コメント数の表示
                        int cmtCnt = json.getJSONObject("comments").getInt("count");
                        itg.setCmtCnt(cmtCnt);
                        mEntries.add(itg);
                    }
                    mAdapter.notifyDataSetChanged();

                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        };
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private class EndlessScrollListener implements AbsListView.OnScrollListener {

        private int visibleThreshold = 5;
        private int previousTotal = 0;
        private boolean loading = true;

        public EndlessScrollListener(){
        }
        public EndlessScrollListener(int visibleThreshold){
            this.visibleThreshold = visibleThreshold;
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {

        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            pd = (ProgressBar)findViewById(R.id.pd);

            if(loading){
                if(totalItemCount > previousTotal){
                    loading = false;
                    previousTotal = totalItemCount;
                    //currentPage++;
                    pd.setVisibility(View.GONE);
                }
            }
            if(!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleItemCount)){
                loadPage();
                loading=true;
                pd.setVisibility(View.VISIBLE);
            }


        }
    }
}



その他

drawableに
適当なアイコン画像
comment.png thumbnail.png
を追加

参考サイト 引用サイト

http://www.androidhive.info/2014/07/android-custom-listview-with-image-and-text-using-volley/
http://k-1-ne-jp.blogspot.jp/2013/09/gridview_20.html