Search This Blog

Sunday 25 March 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 ---
  • You want to make a song list with header to make user interface more interactive
  • There may be many more cases in which we want to give our ListView more fancy way to interact with user
For creating a List-Activtiy or ListView with section wise, we need following thing--
  • Header XML
  • Normal ListRow XML
  • Main Activity with ListView
  • 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

Saturday 17 March 2012

String operations as sorting,splitting and sorting in Android and Java


Collection are very strong tool in android(as well as java).You can sort Array in ASC and DSC order very easily. I take here Mostly Hash Map and Vector 
      

Splitting String by deli-meter and return Vector of string 
       /**
        * @param str
        * @param delimiter -char to which you want to spilt
        * @return Vector of String after splitting
        */
       public Vector<String> SpiltString(String str,char   delimiter){
            str=str.trim();
            TextUtils.SimpleStringSplitter spliter=new SimpleStringSplitter(delimiter);
            spliter.setString(str);
            Vector<String> result=new  Vector<String>();
            for(String temp : spliter ){
             result.add(temp);
            }
            return result;
      }
Removing special characters from string    

How to convert string to bitmap and Bitmap to string


In android, Normally we send and receive data in the form of]string.So if we have image in the Bitmap form then we can not send it to server.So here i made a simple function that you need pass bitmap and it will return a string
     /**
       * @param bitmap
       * @return converting bitmap and return a string
       */
       public String BitMapToString(Bitmap bitmap){
            ByteArrayOutputStream baos=new  ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.PNG,100, baos);
            byte [] b=baos.toByteArray();
            String temp=Base64.encodeToString(b, Base64.DEFAULT);
            return temp;
      }


Tuesday 13 March 2012

Android Listview endless adapter and Pagination

Endless Adapter In android to load quite large amount of data as paging concept

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);
    }
}


Brief Explanation about working It load a fix number of element initially. But when you scroll list down it load more element. It work goes on until you scroll to all element(till the last element). It differ optimize your resource by adding new element after one limit.

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!)

Android News and source code