First Android App | Step 7 | Populate ListView with data from JSON | SearchView and Listview to display search results

In this blog, what we are trying to achieve is the search functionality.

There is a search box on the top. When user tries to enter some text, a restful API will be called on the server with this text as the search text. The returned data which is in JSON format will be parsed and pushed into an ArrayList. Then this ArrayList will be used to populate the ListView of the results.

Once the results are displayed, the user can scroll up or down and there would be a provision for user to add this element to cart as well.

The final result looks like this


The complete video on how to achieve this has been explained in the below video.



The source code is as follows

Update the fragment_search.xml with the following code.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" 
   android:background="#E6E6E6">

    <View
            android:id="@+id/view1"
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:layout_alignParentTop="true"
            android:background="#FFFFFF"
            android:layout_marginTop="5dp"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"/>
    
    <SearchView
        android:id="@+id/searchView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_toLeftOf="@+id/imageButton1"
        android:layout_marginTop="3dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp">
        
    </SearchView>
    
    <ImageButton
        android:id="@+id/imageButton1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginRight="0dp"
        android:layout_marginTop="3dp"
        android:layout_toLeftOf="@+id/imageButton2"
        android:src="@android:drawable/ic_btn_speak_now" />
    
    <ImageButton
        android:id="@+id/imageButton2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="5dp"
        android:layout_marginTop="3dp"
        android:src="@drawable/barcode"/>
    
    
 <ListView
        android:id="@+id/listview_search"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerHorizontal="true"
     android:layout_below="@+id/imageButton2"
        android:layout_marginTop="25dp" 
        android:dividerHeight="5dp"
        android:divider="#E6E6E6"/>
 
</RelativeLayout>

Please the following file listtwo_searchresults.xml in the res/layout folder

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#FFFFFF"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_height="match_parent">
    
    
    <ImageView
        android:id="@+id/productImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_marginTop="5dp"
        android:layout_marginLeft = "5dp"
        android:layout_alignParentTop="True"
        android:src="@drawable/ic_launcher" />
    
    <TextView
        android:id="@+id/product_name"
        android:layout_width="210dp"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/productImage"
        android:layout_marginTop="5dp"
        android:layout_marginLeft="5dp"
        android:text="Product Name"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="#000000"
        android:textSize="18dp" />
    
    <TextView
        android:id="@+id/product_mrp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/productImage"
        android:layout_below="@+id/product_name"
        android:layout_marginTop="5dp"
        android:layout_marginLeft="5dp"
        android:text="MRP:"
        android:textColor="#000000"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textSize="14dp" />
    
    <TextView
        android:id="@+id/product_mrpvalue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/product_mrp"
        android:layout_below="@+id/product_name"
        android:layout_marginTop="5dp"
        android:layout_marginLeft="5dp"
        android:text="Rs 100"
        android:textColor="#000000"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textSize="14dp" />
 
    <TextView
        android:id="@+id/product_bb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/product_mrpvalue"
        android:layout_below="@+id/product_name"
        android:layout_marginTop="5dp"
        android:layout_marginLeft="20dp"
        android:text="BB Price:"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="#000000"
        android:textSize="14dp" />
    
    <TextView
        android:id="@+id/product_bbvalue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/product_bb"
        android:layout_below="@+id/product_name"
        android:layout_marginTop="5dp"
        android:layout_marginLeft="5dp"
        android:text="Rs 95"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="#000000"
        android:textSize="14dp" />

    <Button
        android:id="@+id/add_cart"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_below="@+id/matching_product"
        android:layout_alignParentRight="true"
        android:layout_marginRight ="10dp"
        android:gravity="center"
        android:drawableLeft="@drawable/cart_low" 
        style="?android:attr/borderlessButtonStyle" />
    
</RelativeLayout>


Place the barcode icon in the res/drawable-hdpi folder. Change the name of the file as barcode.jpg





Place the cart icon in the res/drawable-hdpi folder. Change the name of the file as cart_low.jpg





Update the code for Search.java


package com.zing.basket;

package com.zing.basket;

import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.TextView;
import android.widget.Toast;

import com.zing.basket.util.Product;


public class Search extends Fragment
{
 View myFragmentView;
 SearchView search;
 ImageButton buttonBarcode;
 ImageButton buttonAudio;
 Typeface type;
 ListView searchResults;
 String found = "N";
 
 
 //This arraylist will have data as pulled from server. This will keep cumulating.
 ArrayList<Product> productResults = new ArrayList<Product>();
 //Based on the search string, only filtered products will be moved here from productResults
 ArrayList<Product> filteredProductResults = new ArrayList<Product>();
 
 @Override
 public void onCreate(Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
 }
 
 
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
 Bundle savedInstanceState) 
 {
  //get the context of the HomeScreen Activity
  final HomeScreen activity = (HomeScreen) getActivity();
  
  //define a typeface for formatting text fields and listview. 
  
  type= Typeface.createFromAsset(activity.getAssets(),"fonts/book.TTF");
  myFragmentView = inflater.inflate(R.layout.fragment_search, container, false);  
     
  search=(SearchView) myFragmentView.findViewById(R.id.searchView1);
        search.setQueryHint("Start typing to search...");
        
  searchResults = (ListView) myFragmentView.findViewById(R.id.listview_search);
  buttonBarcode = (ImageButton) myFragmentView.findViewById(R.id.imageButton2);
  buttonAudio = (ImageButton) myFragmentView.findViewById(R.id.imageButton1);
  
  
  //this part of the code is to handle the situation when user enters any search criteria, how should the 
  //application behave?
  
  search.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() 
        {
      
      @Override
      public void onFocusChange(View v, boolean hasFocus) {
       // TODO Auto-generated method stub
        
       //Toast.makeText(activity, String.valueOf(hasFocus),Toast.LENGTH_SHORT).show();
      }
     });
  
  search.setOnQueryTextListener(new OnQueryTextListener() 
        {
       
      @Override
      public boolean onQueryTextSubmit(String query) {
       // TODO Auto-generated method stub
        
       return false;
      }
      
      @Override
      public boolean onQueryTextChange(String newText) {
       
        if (newText.length() > 3)
        {
         
         searchResults.setVisibility(myFragmentView.VISIBLE);
         myAsyncTask m= (myAsyncTask) new myAsyncTask().execute(newText);
        }
        else
        {
         
         searchResults.setVisibility(myFragmentView.INVISIBLE);
        }
       
       
               
       return false;
      }
      
     });
  return myFragmentView;
 }  
 
 //this filters products from productResults and copies to filteredProductResults based on search text 

 public void filterProductArray(String newText) 
 {

  String pName;
  
  filteredProductResults.clear();
  for (int i = 0; i < productResults.size(); i++)
  {
   pName = productResults.get(i).getProductName().toLowerCase();
   if ( pName.contains(newText.toLowerCase()) ||
     productResults.get(i).getProductBarcode().contains(newText))
   {
    filteredProductResults.add(productResults.get(i));

   }
  }
  
 }
 
 //in this myAsyncTask, we are fetching data from server for the search string entered by user.
 class myAsyncTask extends AsyncTask<String, Void, String> 
 {
  JSONParser jParser;
  JSONArray productList;
  String url=new String();
  String textSearch;
  ProgressDialog pd;


  @Override
  protected void onPreExecute() {
   super.onPreExecute();
   productList=new JSONArray();
   jParser = new JSONParser();
   pd= new ProgressDialog(getActivity());
   pd.setCancelable(false);
   pd.setMessage("Searching...");
   pd.getWindow().setGravity(Gravity.CENTER);
   pd.show();
  }

  @Override
  protected String doInBackground(String... sText) {
   
   url="http://lawgo.in/lawgo/products/user/1/search/"+sText[0];
   String returnResult = getProductList(url);
   this.textSearch = sText[0];
   return returnResult;
   
  }

  public String getProductList(String url)
  {
   
   Product tempProduct = new Product();
   String matchFound = "N";
   //productResults is an arraylist with all product details for the search criteria
   //productResults.clear();
   
   
   try {
    
    
    JSONObject json = jParser.getJSONFromUrl(url);
    
    productList = json.getJSONArray("ProductList");
  
    //parse date for dateList 
    for(int i=0;i<productList.length();i++)
    {
     tempProduct = new Product();
     
     JSONObject obj=productList.getJSONObject(i);
     
     tempProduct.setProductCode(obj.getString("ProductCode"));
     tempProduct.setProductName(obj.getString("ProductName"));
     tempProduct.setProductGrammage(obj.getString("ProductGrammage"));
     tempProduct.setProductBarcode(obj.getString("ProductBarcode"));
     tempProduct.setProductDivision(obj.getString("ProductCatCode"));
     tempProduct.setProductDepartment(obj.getString("ProductSubCode"));
     tempProduct.setProductMRP(obj.getString("ProductMRP"));
     tempProduct.setProductBBPrice(obj.getString("ProductBBPrice"));
     
     //check if this product is already there in productResults, if yes, then don't add it again. 
     matchFound = "N";
     
     for (int j=0; j < productResults.size();j++)
     {
      
      if (productResults.get(j).getProductCode().equals(tempProduct.getProductCode()))
      {
       matchFound = "Y";    
      }
     }
     
     if (matchFound == "N")
     {
       productResults.add(tempProduct);
     }
     
    }
    
    return ("OK");
    
   } catch (Exception e) {
    e.printStackTrace();
    return ("Exception Caught");
   }
  }
  
  @Override
  protected void onPostExecute(String result) {

   super.onPostExecute(result);
   
   if(result.equalsIgnoreCase("Exception Caught"))
   {
    Toast.makeText(getActivity(), "Unable to connect to server,please try later", Toast.LENGTH_LONG).show();

    pd.dismiss();
   }
   else
   {
  
    
    //calling this method to filter the search results from productResults and move them to 
    //filteredProductResults
    filterProductArray(textSearch);
    searchResults.setAdapter(new SearchResultsAdapter(getActivity(),filteredProductResults));
    pd.dismiss();
   }
  }

 }
}

class SearchResultsAdapter extends BaseAdapter
{
  private LayoutInflater layoutInflater;
  
  private ArrayList<Product> productDetails=new ArrayList<Product>();
  int count;
  Typeface type;
  Context context;
  
  //constructor method
 public SearchResultsAdapter(Context context, ArrayList<Product> product_details) {
 
  layoutInflater = LayoutInflater.from(context);
 
   this.productDetails=product_details;
   this.count= product_details.size();
   this.context = context;
   type= Typeface.createFromAsset(context.getAssets(),"fonts/book.TTF");
   
 }

 @Override
 public int getCount() {
  return count;
 }

 @Override
 public Object getItem(int arg0) {
  return productDetails.get(arg0);
 }

 @Override
 public long getItemId(int arg0) {
  return arg0;
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent) 
 {
  
   ViewHolder holder;
      Product tempProduct = productDetails.get(position);
      
   if (convertView == null) 
      {
       convertView = layoutInflater.inflate(R.layout.listtwo_searchresults, null);
          holder = new ViewHolder();
          holder.product_name = (TextView) convertView.findViewById(R.id.product_name);
          holder.product_mrp = (TextView) convertView.findViewById(R.id.product_mrp);
          holder.product_mrpvalue = (TextView) convertView.findViewById(R.id.product_mrpvalue);
          holder.product_bb = (TextView) convertView.findViewById(R.id.product_bb);
          holder.product_bbvalue = (TextView) convertView.findViewById(R.id.product_bbvalue);
          holder.addToCart = (Button) convertView.findViewById(R.id.add_cart);

    convertView.setTag(holder);
      } 
   else 
      {
             holder = (ViewHolder) convertView.getTag();
      }
  
       
   holder.product_name.setText(tempProduct.getProductName());
   holder.product_name.setTypeface(type);
      
   holder.product_mrp.setTypeface(type);
   
   holder.product_mrpvalue.setText(tempProduct.getProductMRP());
   holder.product_mrpvalue.setTypeface(type);
   
   holder.product_bb.setTypeface(type);
   
   holder.product_bbvalue.setText(tempProduct.getProductBBPrice());
   holder.product_bbvalue.setTypeface(type);
   
      return convertView;
 }
 
  static class ViewHolder 
  {         
         TextView product_name;
         TextView product_mrp;
         TextView product_mrpvalue;
         TextView product_bb;
         TextView product_bbvalue;
         TextView product_savings;
         TextView product_savingsvalue;
         TextView qty;
         TextView product_value;
         Button addToCart;
                
  }
    
}
 


6 comments:

  1. Why don't you post the entire project so that user can download it on a click

    ReplyDelete
  2. can u plz tell us the php code and data base .. how to configure rest api

    ReplyDelete
  3. plz code for php script........

    ReplyDelete
  4. I will post the script shortly on YouTube channel as well as here..

    ReplyDelete