Add CardView to Android OS versions below L ()

You might notice the new CardView widget on Android L preview presentation. The view can be used to display text or images and has a nice shadow.

You can add that view into your project even if you don’t have the minimum API level to “L”… to do that, follow the steps below:

1.  Edit your gradle.build file to:

dependencies {
    // your other dependencies
    compile 'com.android.support:cardview-v7:21.+' // this will load the CardView
}

2. Edit your manifest file and add the following tag

<uses-sdk tools:node="replace" />

Make sure you import the XML schema first in the main tag:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 package="com.yourpackage" >

You might remember that from a previous post.
That will help you fix the Manifest.xml merging issue and avoid the following error:

Error:Execution failed for task ':TestApp:processDebugManifest'.
> Manifest merger failed : uses-sdk:minSdkVersion 14 cannot be smaller than version L declared in library com.android.support:cardview-v7:21.0.0-rc1

3. Use the CardView from the package: android.support.v7.widget like this:

<android.support.v7.widget.CardView
 android:id="@+id/some_card_view"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:layout_alignParentTop="true"
 android:layout_alignParentLeft="true">
<LinearLayout
 android:id="@+id/some_view"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"/>
</android.support.v7.widget.CardView>

That should be all :)

 

 

Android L: RecyclerView Tutorial

Hi,  in today’s tutorial I will show you how to create a list with the newest widget presented at Google I/O 2014, RecyclerView. Also I will show how to add click and long click events within adapter.

WHAT’S DIFFERENT?

  • is a more advanced and flexible version of ListView
  • it forces the implementation of ViewHolde pattern
  • the recycling process is more efficient
  • before you had to create only the ListView and the Adapter, now you have to create the ListView, a LayoutManager and the Adapter.
  • the LayoutManager avoids the calling of findViewById for too many times

 

1. Create a new project and name your main activity MyActivity. (At this step do not write anything in this class).

NOTE: Create your project to support Android L Preview. If you do not have the Android L sdk you can download it from SDK manager.  Your build.gradle file should look like this:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 'android-L'
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "com.example.myapplication"
        minSdkVersion 'L'
        targetSdkVersion 'L'
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:recyclerview-v7:+'
}

2.  Create an xml (or rename the generated one) and name it “my_activity_layout.xml”.

<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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MyActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

3. Create a new xml and name it “item_row.xml”

<?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="horizontal"
    android:gravity="center_vertical"
    android:id="@+id/layout">

    <TextView
        android:id="@+id/rowNumberTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/nameTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

4. Create a new java class for the adapter and name it “MyCustomAdapter”

import android.content.Context;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

public class MyCustomAdapter extends RecyclerView.Adapter<MyCustomAdapter.ViewHolder> implements View.OnClickListener,
        View.OnLongClickListener{

    private ArrayList<String> mDataset;
    private static Context sContext;

    // Adapter's Constructor
    public MyCustomAdapter(Context context, ArrayList<String> myDataset) {
        mDataset = myDataset;
        sContext = context;
    }

    // Create new views. This is invoked by the layout manager.
    @Override
    public MyCustomAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        // Create a new view by inflating the row item xml.
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_row, parent, false);

        // Set the view to the ViewHolder
        ViewHolder holder = new ViewHolder(v);
        holder.mNameTextView.setOnClickListener(MyCustomAdapter.this);
        holder.mNameTextView.setOnLongClickListener(MyCustomAdapter.this);

        holder.mNameTextView.setTag(holder);

        return holder;
    }

    // Replace the contents of a view. This is invoked by the layout manager.
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

        holder.mNumberRowTextView.setText(String.valueOf(position) + ". ");
        // Get element from your dataset at this position and set the text for the specified element
        holder.mNameTextView.setText(mDataset.get(position));

        // Set the color to red if row is even, or to green if row is odd.
        if (position % 2 == 0) {
            holder.mNumberRowTextView.setTextColor(Color.RED);
        } else {
            holder.mNumberRowTextView.setTextColor(Color.GREEN);
        }
    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return mDataset.size();
    }

    // Implement OnClick listener. The clicked item text is displayed in a Toast message.
    @Override
    public void onClick(View view) {
        ViewHolder holder = (ViewHolder) view.getTag();
        if (view.getId() == holder.mNameTextView.getId()) {
            Toast.makeText(sContext, holder.mNameTextView.getText(), Toast.LENGTH_SHORT).show();
        }
    }

    // Implement OnLongClick listener. Long Clicked items is removed from list.
    @Override
    public boolean onLongClick(View view) {
        ViewHolder holder = (ViewHolder) view.getTag();
        if (view.getId() == holder.mNameTextView.getId()) {
            mDataset.remove(holder.getPosition());

            // Call this method to refresh the list and display the "updated" list
            notifyDataSetChanged();

            Toast.makeText(sContext, "Item " + holder.mNameTextView.getText() + " has been removed from list",
                    Toast.LENGTH_SHORT).show();
        }
        return false;
    }

    // Create the ViewHolder class to keep references to your views
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView mNumberRowTextView;
        public TextView mNameTextView;

        /**
         * Constructor
         * @param v The container view which holds the elements from the row item xml
         */
        public ViewHolder(View v) {
            super(v);

            mNumberRowTextView = (TextView) v.findViewById(R.id.rowNumberTextView);
            mNameTextView = (TextView) v.findViewById(R.id.nameTextView);
        }
    }
}

5. Go to your “MyActivity” class and add the following code:

import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.ArrayList;

public class MyActivity extends Activity {

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

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

        // improve performance if you know that changes in content
        // do not change the size of the RecyclerView
        recyclerView.setHasFixedSize(true);

        // use a linear layout manager
        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(mLayoutManager);

        // Data set used by the adapter. This data will be displayed.
        ArrayList<String> myDataset = new ArrayList<String>();
        for (int i= 0; i < 70; i++){
            myDataset.add("Diana " + i);
        }

        // Create the adapter
        RecyclerView.Adapter adapter = new MyCustomAdapter(MyActivity.this, myDataset);
        recyclerView.setAdapter(adapter);
    }
}

Create an emulator which can run Android L (Api Level 20) and run the app.

RecyclerView

Errors after update to Android Studio 0.8

I have just updated my Android Studio to Android Studio 0.8.2. But, after the update I kept getting these 3 errors while I was trying to run my project:

1.  First error

Error:Execution failed for task 
> java.io.FileNotFoundException: C:\Program Files (x86)\Android\android-studio\sdk\tools\proguard\proguard-android-optimize.txt (The system cannot find the path specified)

2. Second error (this happened only after the 1st error had been fixed)

Error:Execution failed for task 
> Manifest merger failed : uses-sdk:minSdkVersion 9 cannot be smaller than version L declared in library com.android.support:appcompat-v7:21.0.0-rc1

3. Third Error (when running the app for Android L)

Error:compileSdkVersion android-L requires compiling with JDK 7

1. First error solution As a workaround I did the following steps:

  • downloaded the proguard txt file (you can download it from here:proguard-android.txt).
  •  renamed it from proguard-android to proguard-android-optimize.txt
  • created a new folder and named it proguard under
 C:\Program Files (x86)\Android\android-studio\sdk\tools\

I don’t know exactly why I got this error as on my the other PC I did the update and everything was ok, but I found on the internet that there are other developers who had this problem (here). 2. Second error solution  So after some research I found out that in one of my modules I had this in the dependencies from build.gradle:

 compile 'com.android.support:appcompat-v7:+'

which I suppose represents the latest version which is 21.0.0.  The support libraries of the preview of Android L work only if the minSDK is Android L. So, as in my case as I didn’t want to run the app for Android L, I had to set specifically the appcompat-v7 to 20 (the latest one before Android L). Below is the code:

compile 'com.android.support:appcompat-v7:20.+'

appcompat-v7.20

 

3.  Third Error Solution

This means that Android L is working only with jdk 7. So in order to fix this error you have to do the following steps:

3.1. Install jdk 7. You can download the .dmg and .exe files from here.

MAC

jdk 7 download

Windows

jdk windows

3.2. After the dmg is downloded click on it to install the jdk.

3.3. After the jdk is installed open Project Structure from here:

project structure

or from File – Project Structure.

3.4.  Now JDK location should be changed from :

MAC OS

/System/Library/Java/JavaVirtualMachines/jdk1.6.0.jdk/Contents/Home

JDK location

to:

/Library/Java/JavaVirtualMachines/jdk1.7.0_55.jdk/Contents/Home

New JDK Location

 Notice that on Mac OS they changed the path from /System/Library to /Library!

Windows 

Change JDK location from:

C:\Program Files\Java\jdk1.6.0_45

jdk location windows

to

C:\Program Files\Java\jdk1.7.0_55

new jdk location windows