Search This Blog

Showing posts with label List view. Show all posts
Showing posts with label List view. Show all posts

Thursday, March 10, 2016

Comparison between android RecyclerView and ListView



Android is an evolving platform. Recently 5.0 (Lollipop) version of Android was released, along with the official RecyclerView support v7 library. As per the official documentation RecyclerView is a major enhancement over ListView. It contains many new features like ViewHolder, ItemDecorator, LayoutManager, and SmoothScroller. But one thing that certainly gives it an edge over the ListView is; the ability to have animations while adding or removing an item. Here in Android RecyclerView vs ListView sum up I would compare the various features of RecyclerView and ListView and form an opinion why it should be used in new implementations.

Differences Between RecyclerView and ListView

1. View Holders

In ListView, defining view holders was a suggested approach for keeping references for views. But it was not a compulsion. Although by not doing so, ListView used show stale data. Another major drawback of not using view holders could lead to a heavy operation of finding views by ids every time. Which resulted in laggy ListViews.

This problem is solved in RecylerView by the use of RecyclerView.ViewHolder class. This is one of the major differences in RecyclerView and ListView. When implementing a RecyclerView this class is used to define a ViewHolder object which is used by the adapter to bind ViewHolder with a position. Another point to be noted here, is that while implementing the adapter for RecyclerView, providing a ViewHolder is compulsory. This makes the implementation a little complex, but solves the issues faced in ListView.


2. Layout Manager

When speaking of ListViews, only one type of ListView is available i.e. the vertical ListView. You cannot implement a ListView with horizontal scroll. I know there are ways to implement a horizontal scroll, but believe me it was not designed to work that way.

But now when we look at Android RecyclerView vs ListView, we have support for horizontal collections as well. In-fact it supports multiple types of lists. To support multiple types of lists it uses RecyclerView.LayoutManager class. This is something new that ListView does not have. RecyclerView supports three types of predefined Layout Managers:


  • LinearLayoutManager – This is the most commonly used layout manager in case of RecyclerView. Through this, we can create both horizontal and vertical scroll lists.
  • GridLayoutManager– This layout manager can be used to display grids, like any picture gallery.

3. Item Animator

Animations in a list is a whole new dimension, which has endless possibilities. In a ListView, as such there are no special provisions through which one can animate, addition or deletion of items. Instead later on as android evolved ViewPropertyAnimator was suggested by Google’s Chet Haase in this video tutorial for animations in ListView.

On the other hand comparing Android RecyclerView vs ListView, it has RecyclerView.ItemAnimator class for handling animations. Through this class custom animations can be defined for item addition, deletion and move events. Also it provides aDefaultItemAnimator, in case you don’t need any customizations.

4. Adapter


ListView adapters were simple to implement. They had a main method getView where all the magic used to happen. Where the views were bound to a position. Also they used to have an interesting method registerDataSetObserver where one can set an observer right in the adapter. This feature is also present in RecyclerView, but RecyclerView.AdapterDataObserver class is used for it. But the point in favor of ListView is that it supports three default implementations of adapters:
ArrayAdapter
CursorAdapter
SimpleCursorAdapter

Whereas RecyclerView adapter, has all the functionality that ListView adapters had except the built in support for DB cursors and ArrayLists. In RecyclerView.Adapter as of now we have to make a custom implementation to supply data to the adapter. Just like a BaseAdapter does for ListViews. 

5. Item Decoration
To display custom dividers in a ListView, one could have easily added these parameters in the ListView XML:


android:divider="@android:color/transparent"
android:dividerHeight="5dp"




The interesting part about Android RecyclerView is that, as of now it does not show a divider between items by default. Although the guys at Google must have left this out for customization, intentionally. But this greatly increases the effort for a developer. If you wish to add a divider between items, you may need to do a custom implementation by using RecyclerView.ItemDecorationclass.

Or you can apply a hack by using this file from official samples: DividerItemDecoration.java

6. OnItemTouchListener
Listviews used to have a simple implementation for detection of clicks, i.e. by the use of AdapterView.OnItemClickListenerinterface.

But on the other hand RecyclerView.OnItemTouchListener interface is used to detect touch events in Android RecyclerView. It complicates the implementation a little, but it gives a greater control to the developer for intercepting touch events. The official documentation states, it can be useful for gestural manipulations as it intercepts a touch event before it is delivered to RecyclerView.

Tuesday, October 7, 2014

Putting the divider in ListView

Here is the code for the divider in android list view.

int[] colors = {0, 0xFFFF0000, 0};
myListview.setDivider(new GradientDrawable(Orientation.RIGHT_LEFT, colors));
myListview.setDividerHeight(1);

This will brought into new gradient styled divider.

Monday, January 7, 2013

LISTVIEW gets refresh and change the value while scroling issue(SOLVED)



First of all main.xml file will be like below:


<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"
    tools:context=".MainActivity" >
    <ListView
        android:id="@+id/list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        
         />
</RelativeLayout>

Row file for the inflator is as 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="match_parent"
    android:orientation="vertical" >
    <SeekBar
        android:id="@+id/seekBar1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:max="100"/>
    <LinearLayout android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal">
        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="click to see row number" />
        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="0" />
    </LinearLayout>
</LinearLayout>




Now the class in the activity should be like this.... See the getview method for the logic of not refreshing the list view after scrolling :


public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

ListView lv = (ListView) findViewById(R.id.list);
lv.setAdapter(new ListAdapter(MainActivity.this));
}

private class ListAdapter extends BaseAdapter {
private Context con;
private int size = 20;
private int s[] = new int[20];

public ListAdapter(MainActivity mainActivity) {
// TODO Auto-generated constructor stub
this.con = mainActivity;
for (int i = 0; i < size; i++) {
s[i] = 0;
}

}

@Override
public int getCount() {
// TODO Auto-generated method stub
return size;
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(final int position, View convertView,ViewGroup parent) {
// TODO Auto-generated method stub
LayoutInflater inflater = LayoutInflater.from(this.con);
View View = inflater.inflate(R.layout.list_row, null);
SeekBar seekbar = (SeekBar) View.findViewById(R.id.seekBar1);
Button btnrow = (Button) View.findViewById(R.id.button1);
final Button btnseek = (Button) View.findViewById(R.id.button2);

seekbar.setProgress(s[position]);
btnseek.setText("" + s[position]);

seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
btnseek.setText("" + progress);
s[position] = progress;

}
});

return View;
}

}

Wednesday, January 2, 2013

Get all the application installed on your system



First of all add the xml for the list of the application installed on your devices.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android1="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <ListView
        android1:id="@+id/listView1"
        android1:layout_width="match_parent"
        android1:layout_height="wrap_content"
        android1:layout_alignParentLeft="true"
        android1:layout_alignParentTop="true" >
    </ListView>

</RelativeLayout>

Here is the code for the row of the list.

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

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="17dp"
        android:layout_marginTop="22dp"
       />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/imageView1"
        android:layout_marginLeft="36dp"
        android:layout_toRightOf="@+id/imageView1"
        android:text="TextView" />

</RelativeLayout>


Now after that add the following code in your main activity.


public class MainActivity extends Activity {

ArrayList<PInfo> arrylist;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PInfo p = new PInfo();

arrylist = getPackages();

for (int i = 0; i < arrylist.size(); i++) {
Log.i("log_tag", "=======" + arrylist.get(i).icon);
}

ListView l = (ListView) findViewById(R.id.listView1);

l.setAdapter(new ListAdatp(this, arrylist));

}

class PInfo {
private String appname = "";
private String pname = "";
private String versionName = "";
private int versionCode = 0;
private String move2sd;
private Drawable icon;

private void prettyPrint() {
Log.v(appname + "\t" + pname + "\t" + versionName + "\t"
+ versionCode, "");
}

}

private ArrayList<PInfo> getPackages() {
ArrayList<PInfo> apps = getInstalledApps(false); /*
* false = no system
* packages
*/

final int max = apps.size();
for (int i = 0; i < max; i++) {
apps.get(i).prettyPrint();

}
return apps;

}

private ArrayList<PInfo> getInstalledApps(boolean getSysPackages) {
ArrayList<PInfo> res = new ArrayList<PInfo>();
List<PackageInfo> packs = getPackageManager().getInstalledPackages(0);
for (int i = 0; i < packs.size(); i++) {
PackageInfo p = packs.get(i);
if ((!getSysPackages) && (p.versionName == null)) {
continue;
}
PInfo newInfo = new PInfo();
newInfo.appname = p.applicationInfo.loadLabel(getPackageManager())
.toString();
newInfo.pname = p.packageName;
newInfo.versionName = p.versionName;
newInfo.versionCode = p.versionCode;
newInfo.icon = p.applicationInfo.loadIcon(getPackageManager());

res.add(newInfo);
}
return res;
}

public class ListAdatp extends BaseAdapter {

Activity ativity;
ArrayList<PInfo> adptarrlist;

public ListAdatp(MainActivity mainActivity, ArrayList<PInfo> arrylist) {

// TODO Auto-generated constructor stub
ativity = mainActivity;
adptarrlist = arrylist;

}

@Override
public int getCount() {
// TODO Auto-generated method stub
return adptarrlist.size();
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(final int position, View convertView,
ViewGroup parent) {
// TODO Auto-generated method stub

LayoutInflater inflt = (LayoutInflater) ativity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

convertView = inflt.inflate(R.layout.listrow, null);

ImageView img = (ImageView) convertView
.findViewById(R.id.imageView1);
TextView txt = (TextView) convertView.findViewById(R.id.textView1);
img.setBackgroundDrawable(adptarrlist.get(position).icon);
txt.setText("(" + adptarrlist.get(position).appname + ")  "
+ adptarrlist.get(position).pname);

txt.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub

Intent LaunchIntent = getPackageManager()
.getLaunchIntentForPackage(
adptarrlist.get(position).pname);
startActivity(LaunchIntent);
}
});

return convertView;
}

}

}

Thursday, December 1, 2011

ADD ELEMENT IN THE LIST AND REMOVE IT BY CLICKING IT

First of all make an XML file called listadapter.xml file and insert the following

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:layout_width="230dp" 
android:layout_height="wrap_content" 
android:id="@+id/myEditText"/>
<Button android:text="Add"
android:id = "@+id/Add"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background = "@drawable/button_shape"
/>
</LinearLayout>
<ListView
android:layout_height="wrap_content" 
android:layout_width="wrap_content" 
android:id="@+id/MyListView">
</ListView>
</LinearLayout>



AND create the class file called ListAdapter.java and insert the following into it



import java.util.ArrayList;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

import android.widget.Toast;


public class ListAdapter extends Activity {
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       Toast.makeText(ListAdapter.this, "Redirecting to List Activity", 400000).show();
     //  TextView textview = new TextView(this);
     //  textview.setText("This is the Artists tab");
       setContentView(R.layout.listadapter);
       Button bt = (Button)findViewById(R.id.Add); 
       ListView lv = (ListView)findViewById(R.id.MyListView);
       final EditText myEditText= (EditText)findViewById (R.id.myEditText);
       final ArrayList<String> videolinks = new ArrayList<String>();
       final ArrayAdapter<String> aa;
       
       aa= new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,videolinks);
       
       lv.setAdapter(aa);
       
       bt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(myEditText.getText().length() != 0)
{
videolinks.add(0, myEditText.getText().toString().trim());
aa.notifyDataSetChanged();
myEditText.setText("");
}
}
       });
       lv.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> arg0, View arg1,int arg2, long arg3) {
// TODO Auto-generated method stub
AlertDialog.Builder ad  = new AlertDialog.Builder(ListAdapter.this);
ad.setTitle("Delete?");
ad.setMessage("Are you sure you want to delete " + arg2);
final int positionToRemove = arg2;
ad.setNegativeButton("Cancel", null);
ad.setPositiveButton("Ok", new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) 
{
               videolinks.remove(positionToRemove);
               aa.notifyDataSetChanged();
       }
});
ad.show();
}
});
  }
}