Search code examples
androidjsonandroid-imageviewpicasso

set images in image in a loop with Picasso


I have a .json like so

 {
        "0": {

            "image_path": "192.168.1.52/test/image/im1.jpg",
            "title": "image 1"
        },
          "1": {

            "image_path": "192.168.1.52/test/image/im2.jpg",
            "title": "image 2"
        },
          "2": {

            "image_path": "192.168.1.52/test/image/im2.jpg",
            "title": "image 3"
        },
  "size": "3"
}

My android portion is...

 RelativeLayout layout= (RelativeLayout) getView().findViewById(R.id.relLayout);
JSONObject jObj = new JSONObject(response);
int size =  Integer.parseInt(jObj.getString("size"));

   for(int i = 0; i < size; i++)
     {
              JSONObject jObj_ =  jObj.getJSONObject(""+i);
                        String image_path_variable = jObj_.getString("image_path");
      }

This is where I'm stuck. I don't know how to insert images dynamically using the path I have in my .json file. so my layout will have multiple image view depending on what the for loop has example of there are 3 images the page will have 3 images what i am saying the my json wont always have 3 images sometimes it will have more then 3 or some times less so the image view needs to be created in the for loop it self

enter image description here


Solution

  • So, step by step in Kotlin.

    My json file (in res > raw > people.json):

    {
      "0": {
        "image_path": "https://images.unsplash.com/photo-1485199692108-c3b5069de6a0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1000&q=80",
        "title": "Girl 1"
      },
      "1": {
        "image_path": "https://images.unsplash.com/photo-1520065949650-380765513210?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1000&q=80",
        "title": "Girl 2"
      },
      "2": {
        "image_path": "https://images.unsplash.com/photo-1547513609-d80733850d2e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1000&q=80",
        "title": "Girl 3"
      },
      "3": {
        "image_path": "https://images.unsplash.com/photo-1550094195-2234fa4e2128?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1000&q=80",
        "title": "Girl 4"
      },
      "size": "4"
    }
    

    Layout for Activity (res > layout > activity_main.xml)

    <?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:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layoutManager="android.support.v7.widget.GridLayoutManager"
            app:spanCount="2" />
    
    </LinearLayout>
    

    Our main activity of the appliaction (MainActivity.kt)

    import android.os.Bundle
    import android.support.v7.app.AppCompatActivity
    import kotlinx.android.synthetic.main.activity_main.*
    import org.json.JSONObject
    
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            setupUi()
        }
    
        private fun setupUi() {
            // Read file content
            val jsonFile = resources
                .openRawResource(R.raw.images)
                .bufferedReader()
                .readText()
    
            // Change "String" in to "Json Object"
            val root = JSONObject(jsonFile)
    
            // Get size of the list
            val size = root.getString("size").toInt()
    
            // Create (empty) list of people
            val peopleList = mutableListOf<Person>()
    
            // Loop to read all of the people
            for (position in 0 until size) {
                val element = root.getJSONObject(position.toString())
    
                // Change json in to Kotlin object
                val photo = Person(
                    element.getString("image_path"),
                    element.getString("title")
                )
    
                // Add element to the list
                peopleList.add(photo)
            }
    
            // Add adapter for RecyclerView
            recycler_view.adapter = PeopleAdapter(this, peopleList)
        }
    }
    

    Element of the list (res > layout > list_item.xml)

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    
        <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/image_view"
            android:layout_width="100dp"
            android:layout_height="150dp"
            android:layout_margin="10dp"
            android:scaleType="centerCrop"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <TextView
            android:id="@+id/title"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:background="@color/colorBlack"
            android:gravity="center"
            android:textColor="@color/colorWhite"
            app:layout_constraintBottom_toBottomOf="@id/image_view"
            app:layout_constraintEnd_toEndOf="@id/image_view"
            app:layout_constraintStart_toStartOf="@id/image_view" />
    
    </android.support.constraint.ConstraintLayout>
    

    Model class representing single element on the list (Person.kt)

    class Person(
        val image: String,
        val title: String
    )
    

    Adapter (using ViewHolder pattern)

    import android.content.Context
    import android.support.v7.widget.RecyclerView
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import com.bumptech.glide.Glide
    import kotlinx.android.synthetic.main.list_item.view.*
    
    class PeopleAdapter(
        private val context: Context,
        private val listOfColor: List<Person>
    ) : RecyclerView.Adapter<PeopleAdapter.ViewHolder>() {
    
        // Creating elements (one item from list)
        override fun onCreateViewHolder(viewGroup: ViewGroup, p1: Int): ViewHolder {
            val view = LayoutInflater
                .from(viewGroup.context)
                .inflate(R.layout.list_item, viewGroup, false)
    
            return ViewHolder(view)
        }
    
        // Number of elements
        override fun getItemCount(): Int = listOfColor.size
    
        // Fill elements with a data
        override fun onBindViewHolder(row: ViewHolder, position: Int) {
            row.bind(position)
        }
    
        // Class responsible for one (single) row
        inner class ViewHolder(private val item: View) : RecyclerView.ViewHolder(item) {
            fun bind(position: Int) {
                // Get image address
                val person = listOfColor[position]
    
                // Load image
                Glide.with(context).load(person.image).into(item.image_view)
    
                // Set text
                item.title.text = person.title
            }
        }
    }
    

    Remember about three (3) dependencies

    implementation 'com.android.support:recyclerview-v7:28.0.0'
    implementation "com.github.bumptech.glide:glide:4.8.0"
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    

    And (1) persmission in (manifest)

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

    Colors (in res > values > colors.xml)

    <color name="colorWhite">#FFF</color>
    
    <!-- Black with 50% transparency -->
    <color name="colorBlack">#80000000</color>
    

    And expected output: enter image description here