Showing posts with label Android Listview. Show all posts
Showing posts with label Android Listview. Show all posts

Monday, April 16, 2012

Creating Horizontal ListView in Android

Today i am going to describing a powerful tool of android, Horizontal Listview with complete source in the end.
Horizontal ListView sometimes is very useful and it save our day.

If you need some explanation then read complete step else download code with link in the end and play with it



Step 1) Create one new Project name HorizontalListviewDemo

Step 2) Change your main activity to as follow class



 package com.ahmad;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;


public class SecondActivity extends Activity implements OnClickListener {
 Button btn1, btn2, btn3, btn4;
 public LinearLayout middle;
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
  btn1 = (Button) findViewById(R.id.btn1);
  btn1.setOnClickListener(this);
  btn2 = (Button) findViewById(R.id.btn2);
  btn2.setOnClickListener(this);
  btn3 = (Button) findViewById(R.id.btn3);
  btn3.setOnClickListener(this);
  try {
   btn4 = (Button) findViewById(R.id.btn4);
   btn4.setOnClickListener(this);
  } catch (Exception e) {
   e.getMessage();
  }
 }


 @Override
 public void onClick(View v) {
  if (v.getId() == R.id.btn1) {
   Toast.makeText(this, "Second Act Btn1 Clicked", Toast.LENGTH_LONG)
     .show();
  } else if (v.getId() == R.id.btn2) {
   Toast.makeText(this, "Second Act Btn 2 Clicked", Toast.LENGTH_LONG)
     .show();
  } else if (v.getId() == R.id.btn3) {
   Toast.makeText(this, "Second Act Btn 3 Clicked", Toast.LENGTH_LONG)
     .show();
  } else if (v.getId() == R.id.btn4) {
   Toast.makeText(this, "Second Act Btn 4 Clicked", Toast.LENGTH_LONG)
     .show();
  }
 }
}


Step 3)Change your main.xml to following



     <?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:background="#FFF"
    android:orientation="vertical" >


    <RelativeLayout
        android:id="@+id/top"
        android:layout_width="fill_parent"
        android:layout_height="55dp"
        android:layout_alignParentTop="true"
        android:background="@drawable/header" >


        <Button
            android:id="@+id/btn_back"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:layout_marginLeft="5dp"
            android:text="@string/back" />
        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:layout_centerVertical="true"
            android:text="@string/title"
            android:textColor="#FFF"
            android:textSize="20dp"
            android:textStyle="bold" />
        <Button
            android:id="@+id/btn_unknown"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="5dp"
            android:text="@string/unknow" />
    </RelativeLayout>
    <HorizontalScrollView
        android:id="@+id/bottom"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:fadeScrollbars="false"
        android:scrollbars="none" >
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/header"
            android:orientation="horizontal" 
            android:paddingTop="5dp" >
            <Button
                android:id="@+id/btn1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/btn1" />
            <Button
                android:id="@+id/btn2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/btn2" />
            <Button
                android:id="@+id/btn3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/btn3" />
            <Button
                android:id="@+id/btn4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/btn4" />
        </LinearLayout>
         </HorizontalScrollView>
        <LinearLayout
        android:id="@+id/middlebar"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_above="@id/bottom"
        android:layout_below="@id/top" >
       </LinearLayout>
      </RelativeLayout>
  
Now enjoy after running it.complete source link is below.See more article on ListView in blog tag Android ListView
                                                    Download Complete Project

Sunday, March 25, 2012

Android ListView with Section Header

ListView is most power full Widget  in android.I have mention it every time i post related to ListView.We have already learned how to create a ListView with  BaseAdapter.Now in above case if you have following problem---

1)You want to make a song list with header to make user interface more interactive
2)There may be many more cases in which we want to give our ListView more fancy way to interact with user

For Implementing these header like ListView or MultipleListItem, we need following thing--

1)Header XML
2)Normal ListRow XML
3)Main Activity with ListView
4)Adapter class



Now  i am going to explain with code now step by step

Step 1) Create one New project

Step 2) Create XML name item1.xml inside res/layout folder.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="fill_parent">
<TextView
android:id="@+id/text"
android:layout_height="50dp"
android:gravity="center_vertical"
android:text="text"
android:visibility="visible"
android:layout_width="fill_parent"
android:textColor="#FF000000"
android:background="#FFFFFFFF" />
</LinearLayout>

Step 3) Create XML name item2.xml inside res/layout folder


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="fill_parent">
<TextView
android:id="@+id/textSeparator"
android:layout_height="wrap_content"
android:gravity="center"
android:text="text"
android:visibility="visible"
android:layout_width="fill_parent"
android:textColor="#FFFFFFFF"
android:background="#000" />
</LinearLayout>

Step 4)Change your activity to List-activity.You can implement with a normal activity. For this you have to take main.xml with ListView.

paste this code inside your list-activity



package com.ahmad.list;

import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.TreeSet;

public class MultipleItemsList extends ListActivity implements OnTouchListener{

    private MyCustomAdapter mAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAdapter = new MyCustomAdapter();
        for (int i = 1; i < 50; i++) {
            mAdapter.addItem("Sameer Blog " + i);
            if (i % 4 == 0) {
                mAdapter.addSeparatorItem("Ahmad " + i);
            }
        }
        setListAdapter(mAdapter);
    }
 //Adapter Class
 private class MyCustomAdapter extends BaseAdapter {

        private static final int TYPE_ITEM = 0;
        private static final int TYPE_SEPARATOR = 1;
        private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;

        private ArrayList<String> mData = new ArrayList<String>();
        private LayoutInflater mInflater;

        private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();

        public MyCustomAdapter() {
            mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        public void addItem(final String item) {
            mData.add(item);
            notifyDataSetChanged();
        }

        public void addSeparatorItem(final String item) {
            mData.add(item);
            // save separator position
            mSeparatorsSet.add(mData.size() - 1);
            notifyDataSetChanged();
        }

        @Override
        public int getItemViewType(int position) {
            return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
        }

        @Override
        public int getViewTypeCount() {
            return TYPE_MAX_COUNT;
        }

        public int getCount() {
            return mData.size();
        }

        public String getItem(int position) {
            return mData.get(position);
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            int type = getItemViewType(position);
            System.out.println("getView " + position + " " + convertView + " type = " + type);
            if (convertView == null) {
                holder = new ViewHolder();
                switch (type) {
                    case TYPE_ITEM:
                        convertView = mInflater.inflate(R.layout.item1, null);
                        holder.textView = (TextView)convertView.findViewById(R.id.text);
                        break;
                    case TYPE_SEPARATOR:
                        convertView = mInflater.inflate(R.layout.item2, null);
                        holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
                        break;
                }
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder)convertView.getTag();
            }
            holder.textView.setText(mData.get(position));
            return convertView;
        }

    }

    public static class ViewHolder {
        public TextView textView;
    }

public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
}




Screen Shot of output of this Program ---

Feel free to comment for suggestion and issue

Tuesday, March 13, 2012

Endless Apapter in android ListView,Paging :android

Endless Adapter In android



In android this is the basic step to implement paging concept in ListView .Or we can say dynamic loading of element.Listview is very useful and powerful view in android.So this will help you a lot.

Here is List-Activity that use Array-Adapter.We set data to adapter by generating some number with the help of A-Synchronous task.We add number when we scroll down and delete when we scroll up.



public class ListViewStressTest extends ListActivity {
    ArrayAdapter<String> adapter;
    ListView list;
    AsyncTask<Void, String, Void> task;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
        this.list = this.getListView();
        this.list.setAdapter(this.adapter);
        this.task = new AsyncTask<Void, String, Void>() {
            Random r = new Random();
            int[] delete;
            volatile boolean scroll = false;
            @Override
            protected void onProgressUpdate(String... values) {
                if(scroll) {
                    scroll = false;
                    doScroll();
                    return;
                }
                if(values == null) {
                    doDelete();
                    return;
                }
                doUpdate(values);
                if(ListViewStressTest.this.adapter.getCount() > 5000) {
                    ListViewStressTest.this.adapter.clear();
                }
            }
            private void doScroll() {
                if(ListViewStressTest.this.adapter.getCount() == 0) {
                    return;
                }

                int n = r.nextInt(ListViewStressTest.this.adapter.getCount());
                ListViewStressTest.this.list.setSelection(n);
            }

            private void doDelete() {
                int[] d;
                synchronized(this) {
                    d = this.delete;
                }
                if(d == null) {
                    return;
                }
                for(int i = 0 ; i < d.length ; i++) {
                    int index = d[i];
                    if(index >= 0 && index < ListViewStressTest.this.adapter.getCount()) {
                        ListViewStressTest.this.adapter.remove(ListViewStressTest.this.adapter.getItem(index));
                    }
                }
            }

            private void doUpdate(String... values) {
                for(int i = 0 ; i < values.length ; i++) {
                    ListViewStressTest.this.adapter.add(values[i]);
                }
            }

            private void updateList() {
                int number = r.nextInt(30) + 1;
                String[] strings = new String[number];

                for(int i = 0 ; i < number ; i++) {
                    strings[i] = Long.toString(r.nextLong());
                }

                this.publishProgress(strings);
            }

            private void deleteFromList() {
                int number = r.nextInt(20) + 1;
                int[] toDelete = new int[number];

                for(int i = 0 ; i < number ; i++) {
                    int num = ListViewStressTest.this.adapter.getCount();
                    if(num < 2) {
                        break;
                    }
                    toDelete[i] = r.nextInt(num);
                }

                synchronized(this) {
                    this.delete = toDelete;
                }

                this.publishProgress(null);
            }

            private void scrollSomewhere() {
                this.scroll = true;
                this.publishProgress(null);
            }

            @Override
            protected Void doInBackground(Void... params) {
                while(true) {
                    int what = r.nextInt(3);

                    switch(what) {
                        case 0:
                            updateList();
                            break;
                        case 1:
                            deleteFromList();
                            break;
                        case 2:
                            scrollSomewhere();
                            break;
                    }

                    try {
                        Thread.sleep(0);
                    } catch(InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }

        };

        this.task.execute(null);
    }
}

IllegalStateException: The content of the adapter has changed but ListView did not receive a notification

This is very common problem when we are updating listview's adapter value Let me try to explain what is happening here - When you create a with an Adapter backing it up, the ListView gets its data by asking the adapter for it. Every time you scroll, the ListView is asking the Adapter for the new items that you scrolled into.
Normally you create the ListView, you create the Adapter, you set the adapter on the listview, and you are done. Android OS takes care of the rest. What you are attempting to do, however, is a bit more complicated. You are trying to occasionally update the data in the adapter. You can imagine that the listview would need to be informed if the adapter data changed, right? If you are displaying a list with 2 items, and you suddenly add 2 more items to the adapter, then the list should now be displaying 4 items! However, it would be really inefficient if the listview had to be continually checking to see if the adapter has changed, right? So what needs to happen is the listview will assume that the adapter doesn't change, and the adapter will notify the listview if it does change. (This agreement between the listview and the adapter allows other benefits, such as the listview can cache some of the items retrieved from the adapter for quick access. Aka if there are 10 list items displayed on the screen, the list may have actually already requested 14 items. That way if you scroll up or down, for at least 2 items in either direction the ListView already has the data to display!)


What you have failed to do, however, is to notify the listview that the data inside of the adapter changed.

So one solution for this problem is to call method listAdapter.notifyDataSetChanged();


this solution is not full proof yet.

I have gone through stack overflow and Google group so i am combining all solution may any of them help you

1)By Jerry Fan     
 I have a fix for this. Just set the visibility of your List View to Gone during
 update and back to visible after update. By doing so, u can avoid the
 inconsistency of your adapter and ListView item count.

2)Almost work in each case listAdapter.notifyDataSetChanged();

Now code how to use these

public class ListViewStressTest extends ListActivity {
    ArrayAdapter<String> adapter;
    ListView list;
    AsyncTask<Void, String, Void> task;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
        this.list = this.getListView();
        this.list.setAdapter(this.adapter);
        this.task = new AsyncTask<Void, String, Void>() {
            Random r = new Random();
            int[] delete;
            volatile boolean scroll = false;
            @Override
            protected void onProgressUpdate(String... values) {
                if(scroll) {
                    scroll = false;
                    doScroll();
                    return;
                }
                if(values == null) {
                    doDelete();
                    return;
                }
                doUpdate(values);
                if(ListViewStressTest.this.adapter.getCount() > 5000) {
                    ListViewStressTest.this.adapter.clear();
                }
            }
            private void doScroll() {
                if(ListViewStressTest.this.adapter.getCount() == 0) {
                    return;
                }

                int n = r.nextInt(ListViewStressTest.this.adapter.getCount());
                ListViewStressTest.this.list.setSelection(n);
            }

            private void doDelete() {
                int[] d;
                synchronized(this) {
                    d = this.delete;
                }
                if(d == null) {
                    return;
                }
                for(int i = 0 ; i < d.length ; i++) {
                    int index = d[i];
                    if(index >= 0 && index < ListViewStressTest.this.adapter.getCount()) {
                        ListViewStressTest.this.adapter.remove(ListViewStressTest.this.adapter.getItem(index));
                    }
                }
            }

            private void doUpdate(String... values) {
                for(int i = 0 ; i < values.length ; i++) {
                    ListViewStressTest.this.adapter.add(values[i]);
                }
            }

            private void updateList() {
                int number = r.nextInt(30) + 1;
                String[] strings = new String[number];

                for(int i = 0 ; i < number ; i++) {
                    strings[i] = Long.toString(r.nextLong());
                }

                this.publishProgress(strings);
            }

            private void deleteFromList() {
                int number = r.nextInt(20) + 1;
                int[] toDelete = new int[number];

                for(int i = 0 ; i < number ; i++) {
                    int num = ListViewStressTest.this.adapter.getCount();
                    if(num < 2) {
                        break;
                    }
                    toDelete[i] = r.nextInt(num);
                }

                synchronized(this) {
                    this.delete = toDelete;
                }

                this.publishProgress(null);
            }

            private void scrollSomewhere() {
                this.scroll = true;
                this.publishProgress(null);
            }

            @Override
            protected Void doInBackground(Void... params) {
                while(true) {
                    int what = r.nextInt(3);

                    switch(what) {
                        case 0:
                            updateList();
                            break;
                        case 1:
                            deleteFromList();
                            break;
                        case 2:
                            scrollSomewhere();
                            break;
                    }

                    try {
                        Thread.sleep(0);
                    } catch(InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }

        };

        this.task.execute(null);
    }
}

Tuesday, January 17, 2012

Creating Listview using BaseAdapter

Here using List view we can customize List View's as we want by using Base Adapter.Here Base Adapter return one view for each row in getView() method.Main thing about Base Adapter
are following--
1) getView() create a new view when it call first time else it will return an already created view (this is called recycled of view).That's why it make List View scrolling faster

2)getCount() you can limit the number of row by returning a value here

If you want to inflate a complete layout in each row then we have to use LayoutInflatre .I explain here with a layout inflating in each row.So our first step will be to create a layout for row

1).Create one layout for one row



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

<ImageView
android:id="@+id/icon"
android:layout_width="22px"
android:layout_height="22px"
android:layout_marginLeft="4px"
android:layout_marginRight="10px"
android:layout_marginTop="4px"
android:src="@drawable/ic_launcher" >
</ImageView>

<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@+id/label"
android:textSize="20px" >
</TextView>

</LinearLayout>
2)Now Create one adapter class
public class MySimpleArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private final String[] values;

public MySimpleArrayAdapter(Context context, String[] values) {
super(context, R.layout.rowlayout, values);
this.context = context;
this.values = values;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.rowlayout, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.label);
ImageView imageView = (ImageView) rowView.findViewById(R.id.icon);
textView.setText(values[position]);
// Change the icon for Windows and iPhone
String s = values[position];
if (s.startsWith("Windows7") || s.startsWith("iPhone")
|| s.startsWith("Solaris")) {
imageView.setImageResource(R.drawable.no);
} else {
imageView.setImageResource(R.drawable.ok);
}

return rowView;
}
}
3)Create one activity class
public class MyListActivity extends ListActivity {
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
String[] values = new String[] { "Android", "iPhone", "WindowsMobile",
"Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X",
"Linux", "OS/2" };
MySimpleArrayAdapter adapter = new MySimpleArrayAdapter(this, values);
setListAdapter(adapter);
}

}
That will show following design in android

If you want to set onClicklistener to your list view then change your activity class to following
public class MyList extends ListActivity {


/** Called when the activity is first created. */

public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Create an array of Strings, that will be put to our ListActivity
String[] names = new String[] { "Linux", "Windows7", "Eclipse", "Suse",
"Ubuntu", "Solaris", "Android", "iPhone" };
ArrayAdapter<String> adapter = new MyPerformanceArrayAdapter(this, names);
setListAdapter(adapter);
ListView list = getListView();
list.setOnItemLongClickListener(new OnItemLongClickListener() {

@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(MyList.this,
"Item in position " + position + " clicked",
Toast.LENGTH_LONG).show();
// Return true to consume the click event. In this case the
// onListItemClick listener is not called anymore.
return true;
}
});
}

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
// Get the item that was clicked
Object o = this.getListAdapter().getItem(position);
String keyword = o.toString();
Toast.makeText(this, "You selected: " + keyword, Toast.LENGTH_SHORT)
.show();

}

}