Android Material Design Master detail example with Material ListView and Cards - ADD, UPDATE AND DELETE DATA

Android Master detail CRUD example with material listview right here. We see how to add ,edit and delete data to and from our material list from our crud activity.

Each material Card in our list has two buttons new and edit. When new is clicked we open crud activity for adding new data. When edit is clicked we open the same activity for editing selected data.

To edit we pass a serialized object to Crud activity. Users can not only edit that passed data but also delete it. We use a class with a static arraylist as our data source. We will buiding our input forms programmatically using Form-Master library, alibrary that enables you build bigger forms with headers easily programmatically.

Common Questions this example explores

  • Android Material List CRUD master detail example.
  • Android Material ListView add update delete with Cards.
  • Android open activity and pass serialized object.

Tools Used

This example was written with the following tools:

  • Windows 8
  • AndroidStudio IDE
  • Genymotion Emulator
  • Language : Java
  • Topic : Material List CRUD, Material List Master Detail, Activity master detail

Libaries Used

Lets jump directly to the source code.

1. Build.Gradle App Level

  • Our app level build.gradle file.
  • Our minimum sdk version is API level 16 as we are using the FormMaster library to build input forms.
  • We also add material list library.
apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.0"
    defaultConfig {
        applicationId "com.tutorials.hp.materiallistviewmasterdetail"
        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 {
    compile fileTree(dir: 'libs', include: ['*.jar'])

    compile 'com.android.support:appcompat-v7:26.+'
    compile 'com.android.support:design:26.+'
    compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha7'
    compile 'com.github.dexafree:materiallist:3.2.1'
    compile 'me.riddhimanadib.form-master:form-master:1.0.2'
}

2. Galaxy.java

  • Our Galaxy class.
  • Our data object. Properties are name,description and image.
  • Implements Serializable class.
package com.tutorials.hp.materiallistviewmasterdetail.mData;

import java.io.Serializable;

public class Galaxy implements Serializable{

    private String name,description;
    private int id,image;
    /*
    - Constructor
     */
    public Galaxy(String name, String description, int id, int image) {
        this.name = name;
        this.description = description;
        this.id = id;
        this.image = image;
    }
    /*
    - Getters
     */
    public String getName() {
        return name;
    }
    public String getDescription() {
        return description;
    }
    public int getId() {
        return id;
    }
    public int getImage() {
        return image;
    }
}

3. DataHolder.java

  • Our data holder class
  • Contains a static arraylist that acts as our data source.
package com.tutorials.hp.materiallistviewmasterdetail.mData;

import com.tutorials.hp.materiallistviewmasterdetail.R;
import java.util.ArrayList;

public class DataHolder {

    public static ArrayList<Galaxy> galaxies=new ArrayList<>();
    /*
    - Return galaxies with initial data.
     */
    public static ArrayList<Galaxy> getData()
    {
        if(galaxies.size() == 0)
        {
            Galaxy g=new Galaxy("Galaxy Title","This is the description...",galaxies.size(), R.drawable.cartwheel);
            galaxies.add(g);
        }
        return galaxies;
    }
}

4. MainActivity.java

  • Our MainActivity class.
  • Derives from AppCompatActivity.
  • Methods: onCreate(),initializeViews(),bindData(),createCard(),onResume().
  • We use MaterializeListView as our adapterview to display cards.
  • We create material cards using createCard() method.
  • We bind data to our cards using bindData() method.
  • When new button in card is clicked we open crud activity for adding new data.
  • When edit button is clicked we open crud activity for editing data.
package com.tutorials.hp.materiallistviewmasterdetail;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.Gravity;
import android.view.View;

import com.dexafree.materialList.card.Card;
import com.dexafree.materialList.card.CardProvider;
import com.dexafree.materialList.card.OnActionClickListener;
import com.dexafree.materialList.card.action.TextViewAction;
import com.dexafree.materialList.view.MaterialListView;
import com.squareup.picasso.RequestCreator;
import com.tutorials.hp.materiallistviewmasterdetail.mData.DataHolder;
import com.tutorials.hp.materiallistviewmasterdetail.mData.Galaxy;

public class MainActivity extends AppCompatActivity {

    MaterialListView materialListView;
    /*
    - When activity is created
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this.initializeViews();
    }

    /*
    - Initial Material ListView.
     */
    private void initializeViews() {
        materialListView = (MaterialListView) findViewById(R.id.material_listview);
    }

    /*
    - Bind data to Material ListView.
     */
    private void bindData() {
    materialListView.getAdapter().clearAll();
        for (Galaxy g : DataHolder.getData()) {
            this.createCard(g);
        }
    }
    /*
    - Create Card.
    - Set its title,description and image.
    - Handle action button click events.
    - Set card to adapter.
    - Set adapter to listview.
     */
    private void createCard(final Galaxy g) {
        Card card = new Card.Builder(this)
                .withProvider(new CardProvider())
               .setLayout(R.layout.material_basic_image_buttons_card_layout)
                //.setLayout(R.layout.material_image_with_buttons_card)
                //.setLayout(R.layout.material_basic_buttons_card)
                //.setLayout(R.layout.material_welcome_card_layout)
                //.setLayout(R.layout.material_small_image_card)
               //.setLayout(R.layout.material_big_image_card_layout)
                .setTitle(g.getName())
                .setTitleGravity(Gravity.CENTER_HORIZONTAL)
                .setDescription(g.getDescription())
                .setDescriptionGravity(Gravity.CENTER_HORIZONTAL)
                .setDrawable(g.getImage())
                .setDrawableConfiguration(new CardProvider.OnImageConfigListener() {
                    @Override
                    public void onImageConfigure(@NonNull RequestCreator requestCreator) {
                        //requestCreator.fit();
                        requestCreator.resize(121,121);
                    }
                })
                .addAction(R.id.left_text_button, new TextViewAction(this)
                        .setText("New")
                        .setTextResourceColor(R.color.colorPrimary)
                        .setListener(new OnActionClickListener() {
                            @Override
                            public void onActionClicked(View view, Card card) {
                                Intent i = new Intent(MainActivity.this, CrudActivity.class);
                                Context c = MainActivity.this;
                                c.startActivity(i);
                            }
                        }))
                .addAction(R.id.right_text_button, new TextViewAction(this)
                        .setText("Edit")
                        .setTextResourceColor(R.color.orange_button)
                        .setListener(new OnActionClickListener() {
                            @Override
                            public void onActionClicked(View view, Card card) {
                                Intent i = new Intent(MainActivity.this, CrudActivity.class);
                                i.putExtra("KEY_GALAXY", g);
                                Context c = MainActivity.this;
                                c.startActivity(i);
                            }
                        }))
                .endConfig()
                .build();

        //Add Card to Adapter and set the adapter to material listview.
        materialListView.getAdapter().add(card);
    }

    /*
    - When activity is resumed, bind data
     */
    @Override
    protected void onResume() {
        super.onResume();
    this.bindData();
    }
}

 

5. CrudActivity.java

  • CRUD activity.
  • Derives from appcompatactivity.
  • Receive data from MainActivity.
  • Add/Edit/Delete data.
  • We receive serialized data from mainactivity and deserialize it to get Galaxy object to update.
  • Otherwise if its null then the activity has been opened or adding new data.
package com.tutorials.hp.materiallistviewmasterdetail;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.tutorials.hp.materiallistviewmasterdetail.mData.DataHolder;
import com.tutorials.hp.materiallistviewmasterdetail.mData.Galaxy;
import java.util.ArrayList;
import java.util.List;
import me.riddhimanadib.formmaster.helper.FormBuildHelper;
import me.riddhimanadib.formmaster.model.FormElement;
import me.riddhimanadib.formmaster.model.FormHeader;
import me.riddhimanadib.formmaster.model.FormObject;

public class CrudActivity extends AppCompatActivity {

    RecyclerView recyclerviewForm;
    FormBuildHelper mFormBuilder;
    Button saveBtn,deleteBtn;
    Galaxy galaxy;
    Boolean isForUpdate = true;
    /*
    - When activity is created.
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_crud);

        this.receiveData();
        this.initializeViews();
    }
    /*
    - Initial Views.
    - Create Form Elements.
    - Add/Edit/Delete data.
     */
    private void initializeViews() {
        // Views
        recyclerviewForm = (RecyclerView) findViewById(R.id.recyclerviewForm);
        saveBtn = (Button) findViewById(R.id.saveBtn);
        deleteBtn = (Button) findViewById(R.id.deleteBtn);
        deleteBtn.setEnabled(isForUpdate);

        mFormBuilder = new FormBuildHelper(this, recyclerviewForm);

        //CREATE FORM ELEMENTS
        FormHeader header = FormHeader.createInstance().setTitle("Galaxy Info");
        final FormElement nameEditText = FormElement.createInstance().setType(FormElement.TYPE_EDITTEXT_TEXT_SINGLELINE).setTitle("Galaxy").setHint("galaxy");
        final FormElement descEditText = FormElement.createInstance().setType(FormElement.TYPE_EDITTEXT_TEXT_MULTILINE).setTitle("Description");

        if (isForUpdate) {
            //UPDATE EDITTEXTS WITH GALAXY VALUES
            nameEditText.setValue(galaxy.getName());
            descEditText.setValue(galaxy.getDescription());
        }
        // ADD FORM ELEMENTS TO LIST
        List<FormObject> formItems = new ArrayList<>();
        formItems.add(header);
        formItems.add(nameEditText);
        formItems.add(descEditText);

        // BUILD AND DISPLAY FORM
        mFormBuilder.addFormElements(formItems);
        mFormBuilder.refreshView();

        //SAVE EITHER AFTER EDITING OR FOR NEW ITEM
        saveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (!isForUpdate) {
                    //ADD NEW GALAXY
                    int id = DataHolder.galaxies.size();
                    Galaxy galaxy = new Galaxy(nameEditText.getValue(), descEditText.getValue(), id, R.drawable.cartwheel);
                    DataHolder.galaxies.add(galaxy);

                    //RESET UI
                    nameEditText.setValue("");
                    descEditText.setValue("");
                    mFormBuilder.refreshView();

                    Toast.makeText(getApplicationContext(), "Successfully Saved Data", Toast.LENGTH_SHORT).show();

                } else {

                    if (galaxy != null) {
                        //UPDATE EXISTING DATA
                        int position = galaxy.getId();
                        DataHolder.galaxies.remove(position);
                        Galaxy newGalaxy = new Galaxy(nameEditText.getValue(), descEditText.getValue(), position, R.drawable.canismajoroverdensity);
                        DataHolder.galaxies.add(position, newGalaxy);

                        Toast.makeText(getApplicationContext(), "Successfully Updated Item", Toast.LENGTH_SHORT).show();
                    }
                    else
                    {
                        Toast.makeText(getApplicationContext(), "Galaxy is null.", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        });

        //DELETE DATA
        deleteBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(isForUpdate)
                {
                    if (galaxy != null)
                    {
                        //GET ITEM POSITION AND DELETE
                        int position = galaxy.getId();
                        DataHolder.galaxies.remove(position);

                        //RESET UI
                        nameEditText.setValue("");
                        descEditText.setValue("");
                        mFormBuilder.refreshView();
                        deleteBtn.setEnabled(isForUpdate=false);
                        saveBtn.setEnabled(false);

                        Toast.makeText(getApplicationContext(), "Deleted Successfully.", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        });
    }

    //RECEIVE SERIALIZED OBJECT FROM MAINACTIVITY
    private void receiveData() {
        try {
            //DESERIALIZE DATA FROM MAINACTIVITY
            Intent i = this.getIntent();
            galaxy = (Galaxy) i.getSerializableExtra("KEY_GALAXY");

            if (galaxy == null) {
                isForUpdate = false;
            }

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

6. ActivityMain.xml

  • ActivityMain.xml.
  • This is a template layout for our MainActivity.
<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.tutorials.hp.materiallistviewmasterdetail.MainActivity">

        <com.dexafree.materialList.view.MaterialListView
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:id="@+id/material_listview"/>

</android.support.constraint.ConstraintLayout>

 

7. activity_crud.xml

  • Our activity_crud.xml layout.
  • Root tag is constraintlayout.
  • Contains a RecyclerView and two buttons.
  • We will use the RecyclerView to build our input forms using the Form-Master library.
  • Delete button will delete data. Save button will both add new data and update existing data.
<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.tutorials.hp.materiallistviewmasterdetail.CrudActivity">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:id="@+id/recyclerviewForm"
            android:descendantFocusability="beforeDescendants" />
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/saveBtn"
            android:text="Save"
            android:background="@color/colorPrimary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <Button
            android:id="@+id/deleteBtn"
            android:text="Delete"
            android:background="@color/colorAccent"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        </LinearLayout>
    </LinearLayout>

</android.support.constraint.ConstraintLayout>

How To Run

  1. Download the project.
  2. You'll get a zipped file,extract it.
  3. Open the Android Studio.
  4. Now close, already open project.
  5. From the Menu bar click on File >New> Import Project.
  6. Now Choose a Destination Folder, from where you want to import project.
  7. Choose an Android Project.
  8. Now Click on “OK“.
  9. Done, your done importing the project,now edit it.

More Resources

Resource Link
GitHub Browse Browse
GitHub Download Link Download

Best Regards, Oclemy.

How do You Feel after reading this?

According to scientists, we humans have 8 primary innate emotions: joy, acceptance, fear, surprise, sadness, disgust, anger, and anticipation. Feel free to tell us how you feel about this article using these emotes or via the comment section. This feedback helps us gauge our progress.

Help me Grow.

I set myself some growth ambitions I desire to achieve by this year's end regarding this website and my youtube channel. Am halfway. Help me reach them by:




Recommendations


What do You Think


Previous Post Next Post