Wednesday, 28 August 2013

Wednesday, 17 July 2013

Custom ProgressBar - Horizontal progress bar with dots

This project provides a horizontal progress bar with dots. 
1. Create a class extends View.

public class DotsProgressBar extends View {
public DotsProgressBar(Context context) {
  super(context);
  init(context);
 }

 public DotsProgressBar(Context context, AttributeSet attrs) {
  super(context, attrs);
  init(context);
 }

 public DotsProgressBar(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  init(context);
 }

 private void init(Context context) {
  mRadius = context.getResources().getDimension(R.dimen.circle_indicator_radius);
  // dot fill color
  mPaintFill.setStyle(Style.FILL);
  mPaintFill.setColor(Color.BLACK);
  // dot background color
  mPaint.setStyle(Style.FILL);
  mPaint.setColor(0x33000000);
  start();
 }
}

2. Draw dos in onDraw method

@Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);

  float dX = (widthSize - mDotCount * mRadius * 2 - (mDotCount - 1) * margin) / 2.0f;
  float dY = heightSize / 2;
  for (int i = 0; i < mDotCount; i++) {
   if (i == mIndex) {
    canvas.drawCircle(dX, dY, mRadius, mPaintFill);
   } else {
    canvas.drawCircle(dX, dY, mRadius, mPaint);
   }

   dX += (2 * mRadius + margin);
  }

 }
3. Set dots count
The default cout is 3. You can also set the dots count using setDotsCount(int count) method.


Source Code

Friday, 11 January 2013

Read data from a plist

I am learning iPhone development these days. I need to read data from a plist file into NSArray

Creating a plist

My plist (ClothesArray.plist) is shown as below. It is a little bit complex. There are two dictionaries: US and JP. In each dictionary, it includes a clothes array.
<plist version="1.0">
<dict>
    <key>US</key>
    <dict>
        <key>Clothes</key>
        <array>
            <string>ABC</string>
            <string>DEF</string>
        </array>
     </dict>
     <key>JP</key>
     <dict>
        <key>Clothes</key>
        <array>
            <string>AAA</string>
            <string>XXX</string>
        </array>
     </dict>
</dict>
</plist>

Reading from a plist
What I need is to get the clothes array in each dictionary.

    //Get the path of the plist
    NSString *path = [[NSBundle mainBundle] pathForResource:@"ClothesArray" ofType:@"plist"];
    //Build the Dictionary from the plist
    NSMutableDictionary * dict =  [[NSMutableDictionary alloc] initWithContentsOfFile:path];
    //Get the array by key from the plist
    NSMutableArray *clothesUSMutableArray = [[dict objectForKey:@"US"] objectForKey:@"Clothes"];
     NSMutableArray *clothesJPMutableArray = [[dict objectForKey:@"JP"] objectForKey:@"Clothes"];
    //print
    for(NSString *str in clothesUSMutableArray){
     NSLog(@"%@", str);
    }
Now, I can get the data from the plist into NSArray.

Monday, 5 November 2012

Android Custom ListView Example

Today I am going to  custom my own ListView using the data getting from XML. I will use XmlPullParser to parse XML.
I am going to use BBC News RSS data ( http://feeds.bbci.co.uk/news/rss.xmlas my ListView content.


ListView is a view group that displays a list of scrollable items. The list items are automatically inserted to the list using an Adapter that pulls content from a source such as an array or database query and converts each item result into a view that's placed into the list.


1.ListView Layout

Main Layout is very simple, just  a listview.
activity_main.xml


    
    




2. Row Layout

Create a new XML layout file to design the single row layout. In this Layout we can design ourown layout for each row.
list_item.xml



    
    

    
    


NewsItem.java
package com.example.listview;

public class NewsItem {
//News title
public String mTitle;
//News description
public String mDescription;
}

Secondly, Create an Adapter. Use this adapter to bind the data to the layout.

ListViewAdapter.java
package com.example.listview;

public class NewsItem {
 //News title
 public String mTitle;
 //News description
 public String mDescription;
}

Secondly, Create an Adapter. Use this adapter to bind the data to the layout.

ListViewAdapter.java
package com.example.listview;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class ListViewAdapter extends BaseAdapter {
 private LayoutInflater mInflater;
 private ArrayList mNewsList;
 public ListViewAdapter(Context c) {
  mInflater = (LayoutInflater) c
    .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
 }

 @Override
 public int getCount() {
  if(mNewsList != null){
   return mNewsList.size();
  }
  return 0;
 }

 @Override
 public Object getItem(int position) {  
  return position;
 }

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

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
  if(convertView == null) {
   convertView = mInflater.inflate(R.layout.list_item, null);
  }
  //title
  TextView title = (TextView) convertView.findViewById(R.id.textview_title);
  //description
  TextView desc = (TextView) convertView.findViewById(R.id.textview_description);
  
  //news item
  NewsItem item = mNewsList.get(position);
  //set values
  title.setText(item.mTitle);
  desc.setText(item.mDescription);
  
  return convertView;
 }
 
 public void setData(ArrayList list){
  mNewsList = list;
 }

4. MainActivity Class

In MainActivity class, I use XmlPullParser to parse the RSS and use an ArrayList to store the result, then notify the the Adapter to refresh the ListView.
MainActivity.java
package com.example.listview;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;


import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.view.Menu;
import android.widget.ListView;

public class MainActivity extends Activity {
//BBC RSS Site URL
private static final String RSS_SITE = "http://feeds.bbci.co.uk/news/rss.xml";
//RSS TAG Name
private static final String TAG_ITEM = "item";
private static final String TAG_TITLE = "title";
private static final String TAG_DESC = "description";
private ListViewAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.listview);
mAdapter = new ListViewAdapter(this);
//set adapter
listView.setAdapter(mAdapter);
//use AsyncTask to parse the RSS data
ParseTask task = new ParseTask(this);
task.execute(RSS_SITE);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

private class ParseTask extends
AsyncTask<String, Void, ArrayList<NewsItem>> {
private ProgressDialog dialog;

public ParseTask(Context c) {
dialog = new ProgressDialog(c);
}

@Override
protected void onPreExecute() {
dialog.setMessage("Loading data...");
dialog.show();
}

@Override
protected ArrayList<NewsItem> doInBackground(String... params) {
String strUrl = params[0];
HttpURLConnection httpConnection = null;
InputStream is = null;
try {
URL url = new URL(strUrl);
httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestMethod("GET");
httpConnection.setConnectTimeout(10000);
httpConnection.setReadTimeout(10000);
httpConnection.connect();
int responseCode = httpConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
is = httpConnection.getInputStream();
return parseNews(is);
}

} catch (Exception e) {
// TODO
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (httpConnection != null) {
httpConnection.disconnect();
httpConnection = null;
}
}
return null;
}

@Override
protected void onPostExecute(ArrayList<NewsItem> result) {
//set the result
mAdapter.setData(result);
//notify to refresh
mAdapter.notifyDataSetChanged();

// Close the progress dialog
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}

private ArrayList<NewsItem> parseNews(InputStream in) throws XmlPullParserException, IOException {
ArrayList<NewsItem> newsList = new ArrayList<NewsItem>();
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser pullParser = factory.newPullParser();
pullParser.setInput(in, "UTF-8");
int eventType = pullParser.getEventType();
NewsItem item = null;
while (eventType != XmlPullParser.END_DOCUMENT) {
String tagName;

if (eventType == XmlPullParser.START_TAG) {
tagName = pullParser.getName();
if (tagName.equals(TAG_ITEM)) {
item = new NewsItem();
} else if (tagName.equals(TAG_TITLE)) {
if (item != null) {
item.mTitle = pullParser.nextText();

}

} else if (tagName.equals(TAG_DESC)) {
if (item != null) {
item.mDescription = pullParser.nextText();
}
}
} else if (eventType == XmlPullParser.END_TAG) {
tagName = pullParser.getName();
if (tagName.equals(TAG_ITEM)) {
newsList.add(item);
item = null;

}
}
eventType = pullParser.next();
}
return newsList;
}
}

The result of running is as below.