Android App Testing getting Started!


Testing your app is an integral part of the app development process. Testing allows you to verify the correctness, functional behavior, and usability of your app before it is released publicly. The android support testing library was announced in Google I/o. The library provides samples and APIs to run unit and integration tests. This approach is similar to the one we can find on other platforms, but also this path has already been traveled by other plugins like Robolectric.
Before we get started with testing we will cover the basic of Android testing in this post



WhyUnit testing ?


  1. Unit testing helps to remove or reduce bugs in code.
  2. Second, unit tests provide a source of good documentation. Unit tests serve a form of a sample, or example code, that gives others an appreciation of how to exercise the API that is ingrained in your software. When you work within a team to get an Android application built, you might find that your unit tests provide the guidance fellow developers first turn to when trying to figure out how to use your code.
  3. unit testing often improves the code and the overall design of the software. Easily testable code, it turns out, it's usually better quality code


Rule of thumb,most applications exercise roughly 70 to 80% of their application code by unit tests.
As a general rule, test what could break, and when in doubt, create a unit test around the code that you think might break. By definition, unit tests test the smallest units of code in as isolated a fashion as possible so as to ensure the unit behaves exactly as expected.

Typically in Java Android development, methods in a class are the smallest units of code for which we write unit tests. Testing individual methods that don't call on other code from other methods or other classes are good unit test starting points and are often referred to as logic unit tests.

Functional testing is testing the application against its specifications or use cases. That is, functional tests check that certain expected inputs result in expected outputs. Functional testing is often done by testers or quality assurance analysts.

System testing tests the whole system or application and is accomplished by QA teams.

Usability testing measures how user-friendly an app is or isn't.

External Tools and dependencies to get started with testing your app.

In 2015, Google made some significant improvements to the testing tools available with Android and the Android SDK.
The standard Android testing tools are now available as part of something called the Android testing support library.
As you'll see later, this library is available through the SDK manager. Just like any other Android SDK feature, this makes getting the tools and adding them to your Android development environment, like Android Studio, quick and easy.
It includes AndroidJUnitRunner, JUnit 4 Rules, Espresso, and UI Automator.
More information about these tools and the library, in general, can be found on developers.android.com website, and at the Google GitHub site for Android testing support library.

JUnit is the most popular unit testing framework for Java code. When you need to run your JUnit tests on a device or virtual device, you'll need a runner. JUnit runners create test case instances, execute the test in the test case, and then report results.
It can run JUnit 3 or JUnit 4 test classes on Android devices to include Espresso and UI automator tests, which I'll talk about in a second.
Espresso is a relatively new testing framework. Created in 2013, it is built on top of JUnit and the Android JUnit runner exercise and test the user interface of an Android app. In the past, writing UI tests was difficult and required developers to build in a lot of custom synchronization and wait times in tests for the UI to fully display and behave reliably. Espresso is fast and requires less work on the part of the developers to interact with and check the UI elements.
UI Automator is a tool for testing user interfaces. However, its focus is really on testing the interaction between your app and another third party app or system application, like the Contacts or Settings app. The UI Automator also allows tests to include interaction with device buttons like the volume controls or the on/off button. While not technically part of the Android testing support library, two additional tools to help with Android app testing provided with the Android SDK are Monkey and monkeyrunner.
Monkey is a tool that runs on an emulator or real device, and it generates random user events,that is, clicks, touches, gestures, and system level events like garbage collection against the device. You use Monkey to stress the application and ensure the application behaves well.Monkey watches the device and reports on any application crashes, unhandled exceptions,or application not responding, ANR errors. Monkey is a black box testing tool, meaning it doesn't have to know anything about your app code and it runs from the command line.
Monkeyrunner is a tool that allows writing programs or scripts that control and test an Android device or emulator and all of its applications from outside of Android code, that is, from a workstation connected to the device or emulator.
Monkeyrunner programs are written in Python, and when running on a device or emulator, they send a scripted set of keystrokes, touch events, and other interactions to the system. These scripts can even deploy apps or be programmed to take screenshots of the device.
Robotium is another alternative Android test automation framework. It can be used to test native as well as hybrid apps. Hybrid apps are those that run native Android code as well as have HTML 5 JavaScript parts that run on a device's internal browser or web view. Robotium test cases are written in Java but require minimal knowledge of the application code. Robotium Recorder, an augmenting commercial product, creates test cases by recording user interactions with the app.
In addition, you'll find plenty of commercial and open source tools like Ranorex and Appium to help you improve the quality of your apps, and there are cloud services like Testdroid & firebase testlab that can run your test apps on hundreds of devices hosted in the cloud. These tools can often help augment your overall test strategy and give you a better assurance that your app will behave well in a multitude of platforms.


Android Oauth Login with Google Account with new Google Play Services

New-googleplay-service-signin


To use Google sign in, you need to first set up a project on the server using Google's developer console. Go to accounts.google.com and make sure that you're signed in to your google account. And, if you don't have one, then, create one. So, I'm going to sign in to my account. Once you're signed in, go to https://developers.google.com/mobile/add. This will take you to the screen on the Google servers where you can add a project to your developer account.
So, I'm going to choose Pick a platform, and I'm gonna choose Android App. Now, I've already done this for my existing project. So, I'm just going to show you what it is that I did, and you can follow along with me. So, I can either chose an existing project or make a new one.


androidxu-google-sigin


androidxu-google-sigin


And, since I've already done this, I'm just going to create a temporary example to show you what I did. But, you can make a new project for yourself. So, I'm going to give the project a name. I'm just gonna call it google-signin.
Adding the SHA 1 key

Paste the command in you terminal windows to genrate the SHA 1 key
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android


Once done you can download the google-services.json file and add it your app directory of your project. 



So, let's go into Android studio and finish setting things up. So, in Android studio, I'm going to open the Sign in project. Alright,when it loads, what we're going to do is, in the projects explorer, we're gonna open up the build.gradle for the project Sign in. And under the classpath definition that you see here, we're going to add another one. We're going to add classpath com.google.gms:google-services.

Lets get started!



1. In Android Studio, go to File -> New Project and fill all the details required to create a new project. When it prompts to select a default activity, select Blank Activity and proceed.

Adding Dependencies

2. Open build.gradle and add android design support library  com.android.support:design:23.2.1 and other dependencies.
apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "android.com.google_signin"
        minSdkVersion 10
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.google.android.gms:play-services:8.4.0'
}

apply plugin: 'com.google.gms.google-services'



Next Creating the  layout and adding the custom google signin buttom

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="android.com.google_signin.MainActivity">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Status: "
        android:textSize="24sp"
        android:id="@+id/tvStatusLabel"
        android:textStyle="bold" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Not Connected"
        android:id="@+id/tvStatus"
        android:layout_alignParentTop="true"
        android:textSize="24sp"
        android:layout_toEndOf="@id/tvStatusLabel" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Display Name:"
        android:id="@+id/tvDispNameLabel"
        android:layout_below="@+id/tvStatusLabel"
        android:layout_alignParentStart="true"
        android:textStyle="bold"
        android:textSize="24sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Email: "
        android:id="@+id/tvEmailLabel"
        android:textStyle="bold"
        android:textSize="24sp"
        android:layout_below="@+id/tvDispName"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tvDispName"
        android:layout_alignTop="@+id/tvDispNameLabel"
        android:layout_toEndOf="@+id/tvDispNameLabel"
        android:textSize="24sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tvEmail"
        android:layout_alignTop="@+id/tvEmailLabel"
        android:layout_toEndOf="@+id/tvEmailLabel"
        android:textSize="24sp" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Disconnect"
        android:id="@+id/btnDisconnect"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Sign Out"
        android:id="@+id/btnSignOut"
        android:layout_above="@+id/btnDisconnect"
        android:layout_centerHorizontal="true" />

    <com.google.android.gms.common.SignInButton
        android:id="@+id/btnSignIn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/btnSignOut"
        android:layout_centerHorizontal="true"
        android:visibility="visible" />
</RelativeLayout>

Working with MainActivity.java and Google sign in Api.

So let's scroll down to the onCreate function. And here is a to-do for us to implement the Google sign-ins object, and you can see that the GoogleApiClient is being created right below this. So let's implement that code.

And in the builder we'll pass in GoogleSignInOptions.Default_Sign_In which is pretty much the only one you can pass and then we'll say .requestEmail . All right, so once we've built the Google sign-in options builder, we need to pass that to the Google API client. And to do that we use our familiar add API method.
So right after here I'll type in .addApi and pass in Auth.Google_Sign_In_API along with the Google sign-in options object that we just created, okay. So that creates the sign-in options object, passes it to the Google API client, and that allows us to use the sign-in API.
So what we're going to do is scroll up to the startSignIn function, and what we need to do now is start the sign-in process. So, to invoke the account picker that lets the user choose the account they want to sign in with, we need to create a sign in intent, and then start it. So let's write that code, I'm going to write Intent signInIntent equals Auth.GoogleSignInApi.getSignInIntent. I'm going to pass in the mGoogleApiClient that I've created and then I'm gonna call startActivityForResult with my signInIntent, and a code, and you can see that I've defined a constant up here to indicate that the activity I'm starting for result is the sign-in process, and we'll use that later when the activity result handler is called.
So I'll type Res_Code_Sign_In. All right, so when the user selects the account to sign in with, that's going to cause the onActivityResult function to be called, and onActivityResult is down here. So when this function is called, we're going to check to make sure that what they're doing is the sign-in process and the code is going to extract the GoogleSignInResult and it's going to pass that to a function called the signInResultHandler. So it gets the GoogleSignInResult by calling the getSignInResultFromIntent, which is this intent that's passed in from the end of the process.
So let's go take a look at the signInResultHandler and the signInResultHandler is up here. So this function checks to see if sign-in was successful by calling the result.isSuccess function.And if so, it extracts information such as the user's Display Name, the user's email, and sets those values into the text fields in our layout.


Adding the MainActivty Code


Copy and paste the code to Mainactivity.java


package android.com.google_signin;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.auth.api.signin.GoogleSignInStatusCodes;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.Scopes;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.common.api.Status;

public class MainActivity extends AppCompatActivity implements
        GoogleApiClient.OnConnectionFailedListener,
        View.OnClickListener {

    private static final String TAG = "SIGNIN_EXERCISE";
    private static final int RES_CODE_SIGN_IN = 1001;

    private GoogleApiClient mGoogleApiClient;

    private TextView m_tvStatus;
    private TextView m_tvDispName;
    private TextView m_tvEmail;

    private void startSignIn() {
        // TODO: Create sign-in intent and begin auth flow
        Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
        startActivityForResult(signInIntent, RES_CODE_SIGN_IN);
    }

    private void signOut() {
        // TODO: Sign the user out and update the UI
        Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
                new ResultCallback() {
                    @Override
                    public void onResult(Status status) {
                        m_tvStatus.setText(R.string.status_notsignedin);
                        m_tvEmail.setText("");
                        m_tvDispName.setText("");
                    }
                });
    }

    private void disconnect() {
        // TODO: Disconnect this account completely and update UI
        Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
                new ResultCallback() {
                    @Override
                    public void onResult(Status status) {
                        m_tvStatus.setText(R.string.status_notconnected);
                        m_tvEmail.setText("");
                        m_tvDispName.setText("");
                    }
                });
    }

    private void signInResultHandler(GoogleSignInResult result) {
        Log.d("result=", String.valueOf(result));
        if (result.isSuccess()) {
            GoogleSignInAccount acct = result.getSignInAccount();
            m_tvStatus.setText(R.string.status_signedin);
            try {
                Log.i("Signin",acct.getDisplayName());
                m_tvDispName.setText(acct.getDisplayName());
                m_tvEmail.setText(acct.getEmail());
            }
            catch (NullPointerException e) {
                Log.d(TAG, "Error retrieving some account information");
            }
        }
        else {
            Status status = result.getStatus();
            int statusCode = status.getStatusCode();
            Log.d("StatusCode", String.valueOf(statusCode));
            if (statusCode == GoogleSignInStatusCodes.SIGN_IN_CANCELLED) {
                m_tvStatus.setText(R.string.status_signincancelled);
            }
            else if (statusCode == GoogleSignInStatusCodes.SIGN_IN_FAILED) {
                m_tvStatus.setText(R.string.status_signinfail);
            }
            else {
                m_tvStatus.setText(R.string.status_nullresult);
            }
        }
    }

    // *************************************************
    // -------- ANDROID ACTIVITY LIFECYCLE METHODS
    // *************************************************
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        m_tvStatus = (TextView)findViewById(R.id.tvStatus);
        m_tvDispName = (TextView)findViewById(R.id.tvDispName);
        m_tvEmail = (TextView)findViewById(R.id.tvEmail);

        findViewById(R.id.btnSignIn).setOnClickListener(this);
        findViewById(R.id.btnSignOut).setOnClickListener(this);
        findViewById(R.id.btnDisconnect).setOnClickListener(this);

        // TODO: Create a sign-in options object
        GoogleSignInOptions gso = new GoogleSignInOptions
                .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .requestScopes(new Scope(Scopes.PLUS_LOGIN))
                .build();

        // Build the GoogleApiClient object
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this, this)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .build();

        // TODO: Customize the sign in button
        SignInButton signInButton = (SignInButton) findViewById(R.id.btnSignIn);
        signInButton.setSize(SignInButton.SIZE_WIDE);
        signInButton.setColorScheme(SignInButton.COLOR_DARK);
        signInButton.setScopes(gso.getScopeArray());
    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode,resultCode,data);

        if (requestCode == RES_CODE_SIGN_IN) {
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            signInResultHandler(result);
        }
    }

    // *************************************************
    // -------- GOOGLE PLAY SERVICES METHODS
    // *************************************************
    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d(TAG, "Could not connect to Google Play Services");
    }

    // *************************************************
    // -------- CLICK LISTENER FOR THE ACTIVITY
    // *************************************************
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btnSignIn:
                startSignIn();
                break;
            case R.id.btnSignOut:
                signOut();
                break;
            case R.id.btnDisconnect:
                disconnect();
                break;
        }
    }
}

Run the App
androidxu-google-sigin

Working with Android material Design Recyclerview and CardView



The RecyclerView widget is a more advanced and flexible version of ListView. This widget is a container for displaying large data sets that can be scrolled very efficiently by maintaining a limited number of views. Use the RecyclerView widget when you have data collections whose elements change at runtime based on user action or network events.


We all know how to use ListView in our app and we know if we want to increase the ListView performances we can use a pattern called ViewHolder. This pattern consists of a simple class that holds the references to the UI components for each row in the ListView.

This pattern avoids looking up the UI components all the time the system shows a row in the list. Even if this pattern introduces some benefits, we can implement the ListView without using it at all. RecyclerView forces us to use the ViewHolder pattern.
The RecyclerView class simplifies the display and handling of large data sets by providing:
  • Layout managers for positioning items
  • Default animations for common item operations, such as removal or addition of items
You also have the flexibility to define custom layout managers and animations for RecyclerView widgets.
Figure 1. The RecyclerView widget.
To use the RecyclerView widget, you have to specify an adapter and a layout manager.

Working with CardView

CardView extends the FrameLayout class and lets you show information inside cards that have a consistent look across the platform. CardView widgets can have shadows and rounded corners.

To create a card with a shadow, use the card_view:cardElevation attribute. CardView uses real elevation and dynamic shadows on Android 5.0 (API level 21) and above and falls back to a programmatic shadow implementation on earlier versions.

Lets get Started!
We’ll start this by creating a new project and applying the material theme.
1. In Android Studio, go to File -> New Project and fill all the details required to create a new project. When it prompts to select a default activity, select Blank Activity and proceed.

Adding Dependencies

2. Open build.gradle and add android design support library  com.android.support:design:23.2.1 and other dependencies.
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.2.1'
    compile 'com.android.support:recyclerview-v7:23.2.1'
    compile 'com.android.support:cardview-v7:23.2.1'
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
}
Open colors.xml located under res -> values and add the below color values.
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#1A4B9C</color>
    <color name="colorPrimaryDark">#003791</color>
    <color name="colorAccent">#FF4081</color>
    <color name="textcolor">#000000</color>
</resources>
Open styles.xml located res -> values and add below styles. The styles defined in this styles.xml are common to all the android versions.
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>



Finally open AndroidManifest.xml and modify the theme to our requirement
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="androidxu.com.menucard">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name="androidxu.com.menucard.ListViewActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>
Now we have our app material ready. So let’s start adding and building the layout file to demonstrate horizontal and vertical listview
Create and open Open the layout file of item_horizontal_list activity (res->item_horizontal_list.xml) and add below layout code.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="210dp"
    android:layout_height="wrap_content"
    android:layout_marginRight="5dp">

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

        <ImageView
            android:id="@+id/imageview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"

            android:adjustViewBounds="true"

            android:src="@drawable/mountain" />

        <TextView
            android:id="@+id/txtview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="@string/lorem_ipsum" />

    </LinearLayout>
</android.support.v7.widget.CardView>
Create and open Open the layout file of item_vertical_list activity (res > item_vertical_list.xml) and add below layout code.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/image"
            android:layout_width="100dp"
            android:layout_height="80dp"
            android:contentDescription="@string/app_name"
            android:padding="5dp"
            android:src="@drawable/mountain" />

        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_toRightOf="@+id/image"
            android:text="@string/lorem_ipsum"
            android:textStyle="bold"
            android:layout_marginLeft="5dp"
            android:textColor="@color/textcolor" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/textView"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@+id/image"
            android:layout_below="@+id/text"
            android:layout_marginLeft="5dp"
            android:layout_toEndOf="@+id/image" />

    </RelativeLayout>

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

Open the layout folder  and create a blank layout file which hold the layout of recyclerview
Add a Linearalayout which binds both the list in a scrollview  by creating a new blank layout file activity_list.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:scrollbars="vertical"
    android:padding="@dimen/activity_horizontal_margin">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:textColor="@color/colorPrimaryDark"
        android:textSize="20dp"
        android:text="Recommended for You"
        android:textStyle="bold" />

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

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:textColor="@color/colorPrimaryDark"
        android:text="Top Deals of the Day"
        android:textStyle="bold" />

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

</LinearLayout>
</ScrollView>

Create a HorizontalListAdapter.java which will extend the recylerview to hold the recyclerview .
package androidxu.com.menucard;

import android.app.Activity;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

public class HorizontalListAdapter extends RecyclerView.Adapter<HorizontalListAdapter.ViewHolder> {

    private Activity activity;
    int[] images= {R.drawable.prawan,R.drawable.awadhi_lucknow_biryani,R.drawable.eggwraps,
            R.drawable.chips,R.drawable.mayonnaise,R.drawable.cmp,R.drawable.mixvegwrap};
    String[] food_items={"prawan","awadhi_lucknow_biryani","eggwraps","chips","mayonnaise","companin","mixvegwrap"};


    public HorizontalListAdapter(Activity activity) {
        this.activity = activity;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        LayoutInflater inflater = activity.getLayoutInflater();
        View view = inflater.inflate(R.layout.item_horizontal_list, viewGroup, false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(HorizontalListAdapter.ViewHolder viewHolder, final int position) {
        viewHolder.imageView.setImageResource(images[position]);
        viewHolder.txtview.setText(food_items[position].toUpperCase());

        viewHolder.linearLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Toast.makeText(activity, "Position clicked: " + position, Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public int getItemCount() {
        return images.length;
    }

    /**
     * View holder to display each RecylerView item
     */
    protected class ViewHolder extends RecyclerView.ViewHolder {

        private LinearLayout linearLayout;
        private ImageView imageView;
        private TextView txtview;


        public ViewHolder(View view) {
            super(view);
            imageView = (ImageView) view.findViewById(R.id.imageview);
            txtview = (TextView) view.findViewById(R.id.txtview);
            linearLayout = (LinearLayout) view.findViewById(R.id.layout);
        }
    }
}

Similarly,Create a VerticalListAdapter.java which will extend the vertical recylerview to hold the recyclerview .
package androidxu.com.menucard;

import android.app.Activity;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

public class VerticalListAdapter extends RecyclerView.Adapter {

    private Activity activity;

    public VerticalListAdapter(Activity activity) {
        this.activity = activity;
    }
    int[] images= {R.drawable.prawan,R.drawable.awadhi_lucknow_biryani,R.drawable.eggwraps,
            R.drawable.chips,R.drawable.mayonnaise,R.drawable.cmp,R.drawable.mixvegwrap};
    String[] food_items={"prawan","awadhi_lucknow_biryani","eggwraps","chips","mayonnaise","companin","mixvegwrap"};
    String[] cost={"Rs 200","Rs 300","Rs 150","R 320","Rs 450","Rs 120","Rs 380"};
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = activity.getLayoutInflater();
        View view = inflater.inflate(R.layout.item_recycler_view, parent, false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position) {
       // if ((position + 1) % 2 == 0) {
            viewHolder.imageView.setImageResource(images[position]);
             viewHolder.txtview.setText(food_items[position].toUpperCase());
        viewHolder.txtCost.setText("Cost Per Person "+cost[position]);
       // } else {
          //  viewHolder.imageView.setImageResource(R.drawable.awadhi_lucknow_biryani);
        //}
        viewHolder.container.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(activity, "Position: " + position, Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public int getItemCount() {
        return images.length;
    }

    /**
     * View holder to display each RecylerView item
     */
    protected class ViewHolder extends RecyclerView.ViewHolder {
        private ImageView imageView;
        private TextView txtview;
        private TextView txtCost;
        private RelativeLayout container;

        public ViewHolder(View view) {
            super(view);
            imageView = (ImageView) view.findViewById(R.id.image);
            txtview = (TextView) view.findViewById(R.id.text);
            txtCost= (TextView) view.findViewById(R.id.textView);
            container = (RelativeLayout) view.findViewById(R.id.container);
        }

    }
}


Now add both the view and bind the adapters in ListViewActivity.java
package androidxu.com.menucard;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

public class ListViewActivity extends AppCompatActivity {

    private RecyclerView horizontalList;
    private RecyclerView verticalList;
    private HorizontalListAdapter horizontalAdapter;
    private VerticalListAdapter verticalAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list_view);

        horizontalList = (RecyclerView)findViewById(R.id.horizontal_recycler);
        verticalList = (RecyclerView)findViewById(R.id.recyle_view);

       // horizontalList.setHasFixedSize(true);
        //verticalList.setHasFixedSize(true);

        //set horizontal LinearLayout as layout manager to creating horizontal list view
        LinearLayoutManager horizontalManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        horizontalList.setLayoutManager(horizontalManager);
        horizontalAdapter = new HorizontalListAdapter(this);
        horizontalList.setAdapter(horizontalAdapter);

        //set vertical LinearLayout as layout manager for vertial listview
        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        verticalList.setLayoutManager(layoutManager);
        verticalAdapter = new VerticalListAdapter(this);
        verticalList.setAdapter(verticalAdapter);
    }
}
Run the App

Working with Android Material Support Design-Bottom Navigation Bar


Today we are presenting AndroidBottomSheet which is included in latest support-design libraray.
Bottom sheet comes with two implementations BottomSheetBehavior andBottomSheetFragmentDialog.
There are two major types of bottom sheets:
  • Modal bottom sheets are alternatives to menus or simple dialogs. They can also present deep-linked content from other apps. They are primarily for mobile.
  • Persistent bottom sheets present in-app content.
Elevation distinguishes modal from persistent bottom sheets. Modal bottom sheets rest at a higher elevation than the app’s content; whereas persistent bottom sheets rest at the same elevation as the app and integrate with its content.
On larger screens, where space is less constrained, using alternative surfaces and components such as simple dialogs and menus may be more appropriate than bottom sheets.