These days Android Plays a very important role in running E-Commerce business furthermore there are endless possibilities. There are thousands of applications in play store running an E-Commerce business. What makes your application stand out from this crowd. Beautiful design and user experience play a major role. In this post, we will build Material E-Commerce App Design in an Android Example. Mainly focusing on rich and beautiful design. This will give a great user experience. The homepage consists of a list of products with the name, price, and image of the product.

Download Source Code

Demo

Material E-Commerce App Design in Android Example - loopwiki.com

Material E-Commerce App Design in Android Example

Step 1: The structure of this application contains Activity. Inside activity, we will place  RecyclerView. Create a new Android Studio Project or open existing. First, we need to setup dependency. Open Build.gradle file. Now we will be using CardView to create beautiful material cards and Picasso to load images. Add a dependency for CardView and Picasso in build.gradle file as shown below.

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.loopwiki.e_commercesample"
        minSdkVersion 16
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support:design:26.1.0'
    implementation 'com.android.support:support-v4:26.1.0'

    /*Add Picasso library dependency here*/
    implementation 'com.squareup.picasso:picasso:2.5.2'
   /* Add CardView dependency here*/
    implementation 'com.android.support:cardview-v7:26.1.0'
}

Step 2: Add the below strings, colors and dimen resources to strings.xmlstyles.xml and dimens.xml files

<resources>
    <string name="app_name">Women\'s Fashion</string>
    <string name="action_settings">Settings</string>
    <string name="loading">Please wait Loading…</string>
    <string name="new_product">New</string>
</resources>
<resources>

    <! – Base application theme. – >
    <style name="AppTheme" parent="Base.V7.Theme.AppCompat.Light">
        <! – Customize your theme here. – >
    </style>

    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Light" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

</resources>
<resources>
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
    <dimen name="fab_margin">16dp</dimen>
    <dimen name="margin_8">8dp</dimen>
    <dimen name="margin_4">4dp</dimen>
</resources>

Step 3: Download and copy these files in res -> drawable folder.

Step 4: Create adapters, models, helpers folder inside your projects package name folder.

Step 5:  Create new class models -> Product.java paste the following code into it. This class represents a model of a single product. Every product contains an image, name, price, and whether it is new or not.

public class Product {
    private int imageResourceId;
    private String productName;
    private String productPrice;
    private boolean isLoading = false;
    private boolean isNew = false;

    public Product(int imageResourceId, String productName, String productPrice, boolean isNew) {
        this.imageResourceId = imageResourceId;
        this.productName = productName;
        this.productPrice = productPrice;
        this.isNew = isNew;
    }

    public Product() {
    }
    public boolean isNew() {
        return isNew;
    }

    public int getImageResourceId() {
        return imageResourceId;
    }
    
    public String getProductName() {
        return productName;
    }
    
    public String getProductPrice() {
        return productPrice;
    }
    
    public boolean isLoading() {
        return isLoading;
    }

    public void setLoading(boolean loading) {
        isLoading = loading;
    }
}

Step 6: Create a new layout -> custom_row_product.xml paste the following lines in it. This layout represents the view of a product in the RecyclerView.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardCornerRadius="2dp"
    app:cardElevation="2dp">

    <LinearLayout
        android:id="@+id/productContent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/imageViewProductThumb"
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:scaleType="fitCenter" />

            <TextView
                android:id="@+id/textViewNew"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@color/colorAccent"
                android:paddingBottom="@dimen/margin_4"
                android:paddingEnd="@dimen/margin_8"
                android:paddingStart="@dimen/margin_8"
                android:paddingTop="@dimen/margin_4"
                android:text="@string/new_product"
                android:textColor="@android:color/white" />

        </RelativeLayout>


        <TextView
            android:id="@+id/textViewProductName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="@dimen/margin_8"
            android:layout_marginLeft="@dimen/margin_8"
            android:layout_marginRight="@dimen/margin_8"
            android:layout_marginStart="@dimen/margin_8"
            android:layout_marginTop="@dimen/margin_8"
            android:lines="1"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" />

        <TextView
            android:id="@+id/textViewProductPrice"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/margin_8"
            android:layout_marginEnd="@dimen/margin_8"
            android:layout_marginLeft="@dimen/margin_8"
            android:layout_marginRight="@dimen/margin_8"
            android:layout_marginStart="@dimen/margin_8"
            android:layout_marginTop="@dimen/margin_4"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
            android:textColor="@color/colorAccent" />
    </LinearLayout>

</android.support.v7.widget.CardView>

Step 6: RecyclerView will be populated with two different layouts first is product layout and another is progress layout. Create a new layout -> custom_row_loading.xml. This layout will contain progress bar and TextView showing loading as defined below.

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

    <ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="@dimen/margin_8" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginBottom="@dimen/margin_8"
        android:layout_marginTop="@dimen/margin_4"
        android:text="@string/loading" />

</LinearLayout>

Step 7: Our model and views are ready now we will create the adapter to populate information in RecyclerView. The adapter will populate views according to the condition. Suppose if the app is fetching data from the server then loading view will be populated inside RecyclerView. When products are fetched then it will remove the loading view and will add product views with there pieces of information. Create new class adapters ->ProductsAdapter.java paste below lines in it.

public class ProductsAdapter extends RecyclerView.Adapter {
    List<Product> mProducts;
    Context mContext;
    public static final int LOADING_ITEM = 0;
    public static final int PRODUCT_ITEM = 1;
    int LoadingItemPos;
    public boolean loading = false;

    public ProductsAdapter(Context mContext) {
        mProducts = new ArrayList<>();
        this.mContext = mContext;
    }
    //method to add products as soon as they fetched 
    public void addProducts(List<Product> products) {
        int lastPos = mProducts.size();
        this.mProducts.addAll(products);
        notifyItemRangeInserted(lastPos, mProducts.size());
    }


    @Override
    public int getItemViewType(int position) {
        Product currentProduct = mProducts.get(position);
        if (currentProduct.isLoading()) {
            return LOADING_ITEM;
        } else {
            return PRODUCT_ITEM;
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        //Check which view has to be populated 
        if (viewType == LOADING_ITEM) {
            View row = inflater.inflate(R.layout.custom_row_loading, parent, false);
            return new LoadingHolder(row);
        } else if (viewType == PRODUCT_ITEM) {
            View row = inflater.inflate(R.layout.custom_row_product, parent, false);
            return new ProductHolder(row);
        }
        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        //get current product
        final Product currentProduct = mProducts.get(position);
        if (holder instanceof ProductHolder) {
            ProductHolder productHolder = (ProductHolder) holder;
            //bind products information with view
            Picasso.with(mContext).load(currentProduct.getImageResourceId()).into(productHolder.imageViewProductThumb);
            productHolder.textViewProductName.setText(currentProduct.getProductName());
            productHolder.textViewProductPrice.setText(currentProduct.getProductPrice());
            if (currentProduct.isNew())
                productHolder.textViewNew.setVisibility(View.VISIBLE);
            else
                productHolder.textViewNew.setVisibility(View.GONE);
            
            productHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // user selected product now you can show details of that product 
                    Toast.makeText(mContext, "Selected "+currentProduct.getProductName(), Toast.LENGTH_SHORT).show();
                }
            });
        }

    }

    @Override
    public int getItemCount() {
        return mProducts.size();
    }

    //Holds view of product with information
    private class ProductHolder extends RecyclerView.ViewHolder {
        ImageView imageViewProductThumb;
        TextView textViewProductName, textViewProductPrice, textViewNew;


        public ProductHolder(View itemView) {
            super(itemView);
            imageViewProductThumb = itemView.findViewById(R.id.imageViewProductThumb);
            textViewProductName = itemView.findViewById(R.id.textViewProductName);
            textViewProductPrice = itemView.findViewById(R.id.textViewProductPrice);
            textViewNew = itemView.findViewById(R.id.textViewNew);

        }
    }
    //holds view of loading item 
    private class LoadingHolder extends RecyclerView.ViewHolder {
        public LoadingHolder(View itemView) {
            super(itemView);
        }
    }
    
    //method to show loading 
    public void showLoading() {
        Product product = new Product();
        product.setLoading(true);
        mProducts.add(product);
        LoadingItemPos = mProducts.size();
        notifyItemInserted(mProducts.size());
        loading = true;
    }

    //method to hide loading 
    public void hideLoading() {
        if (LoadingItemPos <= mProducts.size()) {
            mProducts.remove(LoadingItemPos - 1);
            notifyItemRemoved(LoadingItemPos);
            loading = false;
        }

    }
}

Step 8: Now create new class helpers -> Space add following lines to it. This class is a helper class. Using this class we can add space between two RecyclerView items to separate them from each other.

public class Space extends RecyclerView.ItemDecoration {

    private int spanCount;
    private int spacing;
    private boolean includeEdge;
    private int headerNum;

    public Space(int spanCount, int spacing, boolean includeEdge, int headerNum) {
        this.spanCount = spanCount;
        this.spacing = spacing;
        this.includeEdge = includeEdge;
        this.headerNum = headerNum;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int position = parent.getChildAdapterPosition(view) - headerNum; // item position

        if (position >= 0) {
            int column = position % spanCount; // item column

            if (includeEdge) {
                outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
                outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)

                if (position < spanCount) { // top edge
                    outRect.top = spacing;
                }
                outRect.bottom = spacing; // item bottom
            } else {
                outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
                outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)
                if (position >= spanCount) {
                    outRect.top = spacing; // item top
                }
            }
        } else {
            outRect.left = 0;
            outRect.right = 0;
            outRect.top = 0;
            outRect.bottom = 0;
        }
    }
}

Step 9: E-Commerce business can have thousands of products. Fetching all products at once can take a long time. Instead, we can load data in small chunks like five products first then when the user will scroll and want to see more then we will fetch more five as this cycle continues. To achieve this create new class helpers -> EndlessScrollListener.java adds the following code to it.

public abstract class EndlessScrollListener extends RecyclerView.OnScrollListener {
    // The minimum amount of items to have below your current scroll position
    // before loading more.
    private int visibleThreshold =4 ;
    // The current offset index of data you have loaded
    private int currentPage = 0;
    // The total number of items in the dataset after the last load
    private int previousTotalItemCount = 0;
    // True if we are still waiting for the last set of data to load.
    private boolean loading = true;
    // Sets the starting page index
    private int startingPageIndex = 0;

    RecyclerView.LayoutManager mLayoutManager;

    public EndlessScrollListener(GridLayoutManager layoutManager) {
        this.mLayoutManager = layoutManager;
        visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
    }

    public int getLastVisibleItem(int[] lastVisibleItemPositions) {
        int maxSize = 0;
        for (int i = 0; i < lastVisibleItemPositions.length; i++) {
            if (i == 0) {
                maxSize = lastVisibleItemPositions[i];
            }
            else if (lastVisibleItemPositions[i] > maxSize) {
                maxSize = lastVisibleItemPositions[i];
            }
        }
        return maxSize;
    }

    // This happens many times a second during a scroll, so be wary of the code you place here.
    // We are given a few useful parameters to help us work out if we need to load some more data,
    // but first we check if we are waiting for the previous load to finish.
    @Override
    public void onScrolled(RecyclerView view, int dx, int dy) {
        int lastVisibleItemPosition = 0;
        int totalItemCount = mLayoutManager.getItemCount();

        if (mLayoutManager instanceof StaggeredGridLayoutManager) {
            int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null);
            // get maximum element within the list
            lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
        } else if (mLayoutManager instanceof LinearLayoutManager) {
            lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
        } else if (mLayoutManager instanceof GridLayoutManager) {
            lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition();
        }

        // If the total item count is zero and the previous isn't, assume the
        // list is invalidated and should be reset back to initial state
        if (totalItemCount < previousTotalItemCount) {
            this.currentPage = this.startingPageIndex;
            this.previousTotalItemCount = totalItemCount;
            if (totalItemCount == 0) {
                this.loading = true;
            }
        }
        // If it’s still loading, we check to see if the dataset count has
        // changed, if so we conclude it has finished loading and update the current page
        // number and total item count.
        if (loading &amp;&amp; (totalItemCount > previousTotalItemCount)) {
            loading = false;
            previousTotalItemCount = totalItemCount;
        }

        // If it isn’t currently loading, we check to see if we have breached
        // the visibleThreshold and need to reload more data.
        // If we do need to reload some more data, we execute onLoadMore to fetch the data.
        // threshold should reflect how many total columns there are too
        if (!loading &amp;&amp; (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
            currentPage++;
            onLoadMore(currentPage, totalItemCount);
            loading = true;
        }
    }

    // Defines the process for actually loading more data based on page
    public abstract void onLoadMore(int page, int totalItemsCount);

}

Step 10: Now our adapter is ready to attach RecyclerView. This RecyclerView will be inside Activity. Create a new layout -> content_main.xml. This layout will contain RecyclerView as shown below.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_main">

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:id="@+id/recyclerViewProducts"
        android:layout_height="match_parent" />
</FrameLayout>

Step 11: create one more layout ->activity_main.xml. Add following snippet to it.

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>
    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />


</android.support.design.widget.CoordinatorLayout>

Step 12: Finally create activity class package name -> MainActivity.java. In this activity, we will initialize RecyclerView. Then we will fetch data from the server and provide it to the Adapter. The adapter will take care of populating views in RecyclerView.

public class MainActivity extends AppCompatActivity {
    ProductsAdapter productsAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        //Bind RecyclerView from layout to recyclerViewProducts object
        RecyclerView recyclerViewProducts = findViewById(R.id.recyclerViewProducts);

        //Create new ProductsAdapter
        productsAdapter = new ProductsAdapter(this);
        //Create new GridLayoutManager
        GridLayoutManager gridLayoutManager = new GridLayoutManager(this,
                2,//span count no of items in single row
                GridLayoutManager.VERTICAL,//Orientation
                false);//reverse scrolling of recyclerview
        //set layout manager as gridLayoutManager
        recyclerViewProducts.setLayoutManager(gridLayoutManager);

        //Crete new EndlessScrollListener fo endless recyclerview loading
        EndlessScrollListener endlessScrollListener = new EndlessScrollListener(gridLayoutManager) {
            @Override
            public void onLoadMore(int page, int totalItemsCount) {
                if (!productsAdapter.loading)
                    feedData();
            }
        };
        //to give loading item full single row
        gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                switch (productsAdapter.getItemViewType(position)) {
                    case ProductsAdapter.PRODUCT_ITEM:
                        return 1;
                    case ProductsAdapter.LOADING_ITEM:
                        return 2; //number of columns of the grid
                    default:
                        return -1;
                }
            }
        });
        //add on on Scroll listener
        recyclerViewProducts.addOnScrollListener(endlessScrollListener);
        //add space between cards
        recyclerViewProducts.addItemDecoration(new Space(2, 20, true, 0));
        //Finally set the adapter
        recyclerViewProducts.setAdapter(productsAdapter);
        //load first page of recyclerview
        endlessScrollListener.onLoadMore(0, 0);
    }

    //Load Data from your server here
    // loading data from server will make it very large
    // that's why i created data locally
    private void feedData() {
        //show loading in recyclerview
        productsAdapter.showLoading();
        final List<Product> products = new ArrayList<>();
        int[] imageUrls = {R.drawable.img1, R.drawable.img2, R.drawable.img3, R.drawable.img4};
        String[] ProductName = {"Kingsmon Top", "Adidas Top", "Butterfly Top", "White Top"};
        String[] ProductPrice = {"₹594", "₹5000", "₹200", "₹1999"};
        boolean[] isNew = {true, false, false, true};
        for (int i = 0; i < imageUrls.length; i++) {
            Product product = new Product(imageUrls[i],
                    ProductName[i],
                    ProductPrice[i],
                    isNew[i]);
            products.add(product);
        }
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                //hide loading
                productsAdapter.hideLoading();
                //add products to recyclerview
                productsAdapter.addProducts(products);
            }
        }, 2000);

    }
}

Step 13: Define this activity inside manifest.xml file as shown below.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.loopwiki.e_commercesample">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

Step 15: Run the application.

Material E-Commerce App Design in Android Example - Output

If you still have any queries, please post them in the comments section below, I will be happy to help you.

Author

Hello there, My name is Amardeep founder of loopwiki.com. I have experience in many technologies like Android, Java, Php, etc. In this variety of technologies, I love Android App Development. If you have any idea and you want me to develop for you then let's have chat Conatct

12 Comments

    • for this tutorial, we are using GridLayoutManager. You can show one item per row using LinnearLayoutManger.
      Change this line
      recyclerViewProducts.setLayoutManager(gridLayoutManager);
      to
      recyclerViewProducts.setLayoutManager(new LinnearLayoutManger(this));

  1. dhirendra kumar singh Reply

    great sir
    i have a problem element is repeat not complete last item.

    • In this article, I am using the concept of Asynchronous loading. You can use this behavior to load your products from API in small chunks.

    • You can set on click listener on any of view of recyclerview in adapter launch another activity and pass position of current item inside bundle

  2. Great to have a description on how to use this. Because lots of people dont even know how to use sourse code. I am also one of them with little knowledge in programming language. But its a good idea to provide sourse code as well because if begginers made mistake or error appears then it hard to solve the error. Then sourse code come into handy then. You provide both description as well as source code. So great thanks bro

  3. Naroj Kumar Reply

    sir give me more example about e commerce app like add to cart.show cart,etc

    • Thank you fro your valuable feedback. This Tutorial was intended to create material app design for e-commerce application. We will be covering cart in our future post i will let you know when its done.

Write A Comment