Step by Step Guide to create an android application for an Electronic E-Commerce store with a ListView to display products with the product name, image, price, an edit box to edit the product quantity, and two image buttons to increment decrement the product quantity. We will use Kotlin in this guide. If you are looking for the Java version, you can refer to this article.

Before moving ahead, the following is the demo video that we achieve at the end of this article.

Following is the project structure for the demo application. Android Studio Version: Arctic Fox | 2020.3.1 Patch 3

  • Kotlin
    • com.vlemon.listviewedittextbutton
      • Product.kt – A product class.
      • ListAdapter.kt – A Kotlin class for the Custom List Adapter to populate the custom ListView.
      • ListViewHolder.kt – It is a custom item holder Kotlin class for the ListView.
      • MainActivity.kt – It is the main activity class.
  • res
    • layout
      • activity_custom_listview.xml – The layout file defines the arrangement for product image, title, price, quantity, and buttons for each product.
      • activity_main.xml – main activity layout.
  • mipmap-xxxhdpi : ic_minus.png, ic_plus.png, camera_1.png, camera.png, floppy.png, game_controller.png, graphics_card.png, hdmi.png, headphones.png, imac.png, ipad.png, keyboard.png, laptop.png, lcd.png, light_bulb.png, mac_mini.png, monitor.png, mouse.png, movie_camera.png, music_player.png, pc.png, playstation.png, printer.png, remote.png, smart_watch.png, smartphone.png, tablet.png, usb.png, webcam.png, windows_phone.png, zerox.png
  • values
    • colors.xml – You can change it as per your application theme.
    • strings.xml – no changes in this.
    • themes.xml – You may need to change it if you change the colors.xml file.

Follow are the steps.

Step 1: To avoid complexity, we will start with a blank project.

Step 2: Start adding the static items in your project, for example, product images, colors, strings, and themes. 

Note: We are not using any server, so all the resources are locally available within the project.

Step 3: Next, we need to create a new product item layout file with the name “activity_custom_listview.xml.” It is used in the ListView to render each product row. Later, we will create ListAdpter.kt class in Step 7.

				
					<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Place Order"
            android:id="@+id/btnPlaceOrder"
            />
    </LinearLayout>

    <ListView
        android:id="@+id/customListView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toTopOf="@+id/linearLayout" />

</androidx.constraintlayout.widget.ConstraintLayout>
				
			

Step 5: Create a new class with the name Product.kt. It is our product item structure with all the required information in it.

				
					package com.vlemonn.vlog.listviewedittextbutton

class Product(productName: String?, productPrice: Double?, productImage: Int) {

    var ProductName: String? = productName
    var ProductPrice: Double? = productPrice
    var ProductImage = productImage
    var CartQuantity = 0

}
				
			

Step 6: Next, we need to create a list view holder class to store the inflated view components of activity_custom_listview.xml. It is used to store each list view row. It avoids reinitializing the view components of activity_custom_listview.xml while scrolling. Please create a new class for holding our Custom ListView layout view components with the file name ListViewHolder.kt

				
					package com.vlemonn.vlog.listviewedittextbutton

import android.widget.EditText
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView


class ListViewHolder {

    var tvProductName: TextView? = null
    var ivProduct: ImageView? = null
    var tvPrice: TextView? = null
    var btnPlus: ImageButton? = null
    var edTextQuantity: EditText? = null
    var btnMinus: ImageButton? = null
    var llMainRow: LinearLayout? = null

}
				
			

Step 7: Next, we need to create a new list view adapter class. An adapter acts as a bridge between our data sources and ListView (or UI components) to fill data into our ListView (or UI Components). Please create a new Kotlin Class for our custom ListView Adapter ListAdapter.kt.

				
					package com.vlemonn.vlog.listviewedittextbutton

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.EditText
import java.util.ArrayList

class ListAdapter(con: Context?, list: ArrayList<Product>?) : BaseAdapter() {

    var listProducts: ArrayList<Product>? = list
    private var context: Context? = con

    override fun getCount(): Int {
        return listProducts!!.size
    }

    override fun getItem(position: Int): Product {
        return listProducts!![position]
    }

    override fun getItemId(position: Int): Long {
        return 0
    }

    override fun getView(
        position: Int, convertView: View?, parent: ViewGroup?
    ): View {
        val row: View
        val listViewHolder: ListViewHolder
        if (convertView == null) {
            val layoutInflater =
                context!!.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            row = layoutInflater.inflate(R.layout.activity_custom_listview, parent, false)
            listViewHolder = ListViewHolder()
            listViewHolder.tvProductName = row.findViewById(R.id.tvProductName)
            listViewHolder.ivProduct = row.findViewById(R.id.ivProduct)
            listViewHolder.tvPrice = row.findViewById(R.id.tvPrice)
            listViewHolder.btnPlus = row.findViewById(R.id.ib_addnew)
            listViewHolder.edTextQuantity = row.findViewById(R.id.editTextQuantity)
            listViewHolder.btnMinus = row.findViewById(R.id.ib_remove)
            row.tag = listViewHolder
        } else {
            row = convertView
            listViewHolder = row.tag as ListViewHolder
        }
        val products = getItem(position)
        listViewHolder.tvProductName!!.text = products.ProductName
        listViewHolder.ivProduct!!.setImageResource(products.ProductImage)
        listViewHolder.tvPrice!!.text = products.ProductPrice.toString() + " $"
        listViewHolder.edTextQuantity!!.setText(products.CartQuantity.toString())
        listViewHolder.btnPlus!!.setOnClickListener {
            updateQuantity(
                position,
                listViewHolder.edTextQuantity,
                1
            )
        }
        //listViewHolder.edTextQuantity.setText("0");
        listViewHolder.btnMinus!!.setOnClickListener {
            updateQuantity(
                position,
                listViewHolder.edTextQuantity,
                -1
            )
        }
        return row
    }

    private fun updateQuantity(position: Int, edTextQuantity: EditText?, value: Int) {
        val products = getItem(position)
        if (value > 0) {
            products.CartQuantity = products.CartQuantity + 1
        } else {
            if (products.CartQuantity > 0) {
                products.CartQuantity = products.CartQuantity - 1
            }
        }
        edTextQuantity!!.setText(products.CartQuantity.toString())
    }

}
				
			

Step 8: At last, we need to update our Main Activity Kotlin Class. We need to first create some dummy data for the Products. Next, initialize our ListView and the Place Order button. Finally, we need to create a new instance of ListAdapter and assign it to our ListView. In the end, save your work and execute the project.

				
					package com.vlemonn.vlog.listviewedittextbutton

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.ListView
import java.util.ArrayList

class MainActivity : AppCompatActivity() {
    private var listView: ListView? = null
    private lateinit var listAdapter: ListAdapter
    var products = ArrayList<Product>()
    var btnPlaceOrder: Button? = null
    var productOrders = ArrayList<Product>()


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        getProduct()
        listView = findViewById<View>(R.id.customListView) as ListView
        listAdapter = ListAdapter(this, products)
        listView!!.setAdapter(listAdapter)



        btnPlaceOrder = findViewById<View>(R.id.btnPlaceOrder) as Button
        btnPlaceOrder!!.setOnClickListener { placeOrder() }
    }

    private fun placeOrder() {
        productOrders.clear()
        for (i in listAdapter.listProducts!!.indices) {
            if (listAdapter.listProducts!![i].CartQuantity > 0) {
                val products = Product(
                    listAdapter.listProducts!![i].ProductName,
                    listAdapter.listProducts!![i].ProductPrice,
                    listAdapter.listProducts!![i].ProductImage
                )
                products.CartQuantity = listAdapter.listProducts!![i].CartQuantity
                productOrders.add(products)
            }
        }
    }

    fun getProduct() {
        products.add(Product("Video Recorder", 10.0, R.mipmap.camera))
        products.add(Product("Camera", 11.0, R.mipmap.camera_1))
        products.add(Product("Floppy", 12.0, R.mipmap.floppy))
        products.add(Product("Game Pad", 13.0, R.mipmap.game_controller))
        products.add(Product("Graphics Card", 14.0, R.mipmap.graphics_card))
        products.add(Product("HDMI Cable", 16.0, R.mipmap.hdmi))
        products.add(Product("Headphones", 11.0, R.mipmap.headphones))
        products.add(Product("I Mac", 15.0, R.mipmap.imac))
        products.add(Product("I Pad", 17.0, R.mipmap.ipad))
        products.add(Product("Keyboard", 67.0, R.mipmap.keyboard))
        products.add(Product("Laptop", 41.0, R.mipmap.laptop))
        products.add(Product("LCD", 16.0, R.mipmap.lcd))
        products.add(Product("Light Bulb", 18.0, R.mipmap.light_bulb))
        products.add(Product("Mac Mini", 121.0, R.mipmap.mac_mini))
        products.add(Product("Monitor", 122.0, R.mipmap.monitor))
        products.add(Product("Mouse", 14.0, R.mipmap.mouse))
        products.add(Product("Movie Camera", 51.0, R.mipmap.movie_camera))
        products.add(Product("Music Player", 12.0, R.mipmap.music_player))
        products.add(Product("PC", 16.0, R.mipmap.pc))
        products.add(Product("Playstation", 12.0, R.mipmap.playstation))
        products.add(Product("Printer", 17.0, R.mipmap.printer))
        products.add(Product("Remote", 12.0, R.mipmap.remote))
        products.add(Product("Smart Watch", 18.0, R.mipmap.smart_watch))
        products.add(Product("Smartphone", 19.0, R.mipmap.smartphone))
        products.add(Product("Tablet", 21.0, R.mipmap.tablet))
        products.add(Product("USB", 87.0, R.mipmap.usb))
        products.add(Product("Webcam", 87.0, R.mipmap.webcam))
        products.add(Product("Windows Phone", 123.0, R.mipmap.windows_phone))
        products.add(Product("Zerox", 85.0, R.mipmap.zerox))
    }
}
				
			

If the application fails due to a memory issue, you may add android:largeHeap=”true” in the AndroidManifest.xml.

I hope you like this step-by-step guide. You may also like How to use the Place Order Button.

You can download the source code by visiting the following URL.