import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.BaseAdapter;
import android.widget.Checkable;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/** * An easy adapter to map static data to views defined in an XML file. You can specify the data * backing the list as an ArrayList of Maps. Each entry in the ArrayList corresponds to one row * in the list. The Maps contain the data for each row. You also specify an XML file that * defines the views used to display the row, and a mapping from keys in the Map to specific * views. * * Binding data to views occurs in two phases. First, if a * {@link android.widget.SimpleAdapter.ViewBinder} is available, * {@link ViewBinder#setViewValue(android.view.View, Object, String)} * is invoked. If the returned value is true, binding has occurred. * If the returned value is false, the following views are then tried in order: * <ul>
* <li> A view that implements Checkable (e.g. CheckBox). The expected bind value is a boolean. * <li> TextView. The expected bind value is a string and {@link #setViewText(TextView, String)} * is invoked. * <li> ImageView. The expected bind value is a resource id or a string and * {@link #setViewImage(ImageView, int)} or {@link #setViewImage(ImageView, String)} is invoked. * </ul>
* If no appropriate binding can be found, an {@link IllegalStateException} is thrown. */public class MySimpleAdapter extends BaseAdapter implements Filterable {
private int[] mTo;
private String[] mFrom;
private ViewBinder mViewBinder;
// private List<View> mViews;
private List<? extends Map<String, ?>> mData;
private int mResource;
private int mDropDownResource;
private LayoutInflater mInflater;
private SimpleFilter mFilter;
private ArrayList<Map<String, ?>> mUnfilteredData;
private Context mContext;
/** * Constructor * * @param context The context where the View associated with this SimpleAdapter is running * @param data A List of Maps. Each entry in the List corresponds to one row in the list. The * Maps contain the data for each row, and should include all the entries specified in * "from" * @param resource Resource identifier of a view layout that defines the views for this list * item. The layout file should include at least those named views defined in "to" * @param from A list of column names that will be added to the Map associated with each * item. * @param to The views that should display column in the "from" parameter. These should all be * TextViews. The first N views in this list are given the values of the first N columns * in the from parameter. */ public MySimpleAdapter(Context context, List<? extends Map<String, ?>> data,
int resource, String[] from, int[] to) {
mData = data;
mResource = mDropDownResource = resource;
mFrom = from;
mTo = to;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// mViews = new ArrayList<View>(); mContext = context;
}
/** * @see android.widget.Adapter#getCount() */ public int getCount() {
return mData.size();
}
/** * @see android.widget.Adapter#getItem(int) */ public Object getItem(int position) {
return mData.get(position);
}
/** * @see android.widget.Adapter#getItemId(int) */ public long getItemId(int position) {
return position;
}
/** * @see android.widget.Adapter#getView(int, View, ViewGroup) */ public View getView(int position, View convertView, ViewGroup parent) {
return createViewFromResource(position, convertView, parent, mResource);
}
private View createViewFromResource(int position, View convertView,
ViewGroup parent, int resource) {
// if(position >= mViews.size()){// mViews.add(position, mInflater.inflate(resource, parent, false));// }// bindView(position, mViews.get(position));// return mViews.get(position); View v;
if (convertView == null) {
v = mInflater.inflate(resource, parent, false);
} else {
v = convertView;
}
bindView(position, v);
return v;
}
/** * <p>Sets the layout resource to create the drop down views.</p>
* * @param resource the layout resource defining the drop down views * @see #getDropDownView(int, android.view.View, android.view.ViewGroup) */ public void setDropDownViewResource(int resource) {
this.mDropDownResource = resource;
}
@Override public View getDropDownView(int position, View convertView, ViewGroup parent) {
return createViewFromResource(position, convertView, parent, mDropDownResource);
}
private void bindView(int position, View view) {
final Map dataSet = mData.get(position);
if (dataSet == null)
{
return;
}
final ViewBinder binder = mViewBinder;
final String[] from = mFrom;
final int[] to = mTo;
final int count = to.length;
for (int i = 0; i < count; i++)
{
final View v = view.findViewById(to[i]);
if (v != null)
{
final Object data = dataSet.get(from[i]);
String text = data == null ? "" : data.toString();
if (text == null)
{
text = "";
}
boolean bound = false;
if (binder != null)
{
bound = binder.setViewValue(v, data, text);
}
if (!bound)
{
if(data instanceof OnClickListener)
{
v.setOnClickListener((OnClickListener) data);
}
else if(data instanceof OnTouchListener)
{
v.setOnTouchListener((OnTouchListener) data);
}
else if (v instanceof Checkable)
{
if (data instanceof Boolean)
{
((Checkable) v).setChecked((Boolean) data);
}
else if (v instanceof TextView)
{
// Note: keep the instanceof TextView check at the bottom of these // ifs since a lot of views are TextViews (e.g. CheckBoxes). setViewText((TextView) v, text);
}
else {
throw new IllegalStateException(v.getClass().getName() +
" should be bound to a Boolean, not a " +
(data == null ? "<unknown type>" : data.getClass()));
}
}
else if (v instanceof LinearLayout)
{
if (data == null)
{
v.setVisibility(View.INVISIBLE);
}
else if (data instanceof String)
{
if (data.equals("View.GONE"))
{
v.setVisibility(View.GONE);
}
else if (data.equals("View.VISIBLE"))
{
v.setVisibility(View.VISIBLE);
}
else if (data.equals("View.INVISIBLE"))
{
v.setVisibility(View.INVISIBLE);
}
}
// else if (data.equals("GONE")) else if (data.equals(View.GONE))
{
v.setVisibility(View.GONE);
}
// else if (data.equals("VISIBLE")) else if (data.equals(View.VISIBLE))
{
v.setVisibility(View.VISIBLE);
}
else if (data instanceof Integer)
{
Log.d("simpleData", "" + (Integer)data);
((LinearLayout) v).setBackgroundResource((Integer)data);
}
else {
v.setVisibility(View.VISIBLE);
}
}
else if (v instanceof TextView)
{
// Note: keep the instanceof TextView check at the bottom of these // ifs since a lot of views are TextViews (e.g. CheckBoxes). if (text.equals(""))
{
v.setVisibility(View.GONE);
}
else {
setViewText((TextView) v, text);
v.setVisibility(View.VISIBLE);
}
}
else if (v instanceof WebView)
{
// Note: keep the instanceof TextView check at the bottom of these // ifs since a lot of views are TextViews (e.g. CheckBoxes). WebView wv = (WebView) v;
wv.loadDataWithBaseURL(null, text, "text/html", "utf-8",null);
// wv.loadData(text, "text/html", "utf-8");// wv.loadUrl((String) data); WebSettings bs = wv.getSettings();
bs.setDefaultZoom(WebSettings.ZoomDensity.CLOSE);
}
else if (v instanceof ImageView)
{
if(data instanceof ImageLoader){
final int index = i;
((ImageLoader) data).loadImage(new ImageLoader.ImageCallback() {
@SuppressWarnings("deprecation")
@Override public void imageLoaded(Object data) {
dataSet.put(from[index], data);
notifyDataSetChanged();
}
});
}
if (data instanceof Integer)
{
setViewImage((ImageView) v, (Integer) data);
v.setVisibility(View.VISIBLE);
}
else if(data instanceof Bitmap)
{
setImageBitmap((ImageView) v, (Bitmap) data);
v.setVisibility(View.VISIBLE);
}
else if (data instanceof String)
{
if (data.equals("View.GONE"))
{
v.setVisibility(View.GONE);
}
else if (data.equals("View.VISIBLE"))
{
v.setVisibility(View.VISIBLE);
}
else if (data.equals("View.INVISIBLE"))
{
v.setVisibility(View.INVISIBLE);
}
}
else if (data instanceof RelativeLayout.LayoutParams)
{
v.setLayoutParams((LayoutParams)data);
}
else if(data != null)
{
setViewImage((ImageView) v, text);
v.setVisibility(View.VISIBLE);
}
else {
// v.setVisibility(View.INVISIBLE); v.setVisibility(View.GONE);
}
}
else {
if (data instanceof Integer)
{
v.setBackgroundResource((Integer) data);
}
else if(data != null)
{
try {
v.setBackgroundResource(Integer.parseInt(text));
} catch (NumberFormatException nfe) {
}
}
else {
// throw new IllegalStateException(v.getClass().getName() + " is not a " +// " view that can be bounds by this SimpleAdapter"); }
}
}
}
}
}
/** * Returns the {@link ViewBinder} used to bind data to views. * * @return a ViewBinder or null if the binder does not exist * * @see #setViewBinder(android.widget.SimpleAdapter.ViewBinder) */ public ViewBinder getViewBinder() {
return mViewBinder;
}
/** * Sets the binder used to bind data to views. * * @param viewBinder the binder used to bind data to views, can be null to * remove the existing binder * * @see #getViewBinder() */ public void setViewBinder(ViewBinder viewBinder) {
mViewBinder = viewBinder;
}
/** * Called by bindView() to set the image for an ImageView but only if * there is no existing ViewBinder or if the existing ViewBinder cannot * handle binding to an ImageView. * * This method is called instead of {@link #setViewImage(ImageView, String)} * if the supplied data is an int or Integer. * * @param v ImageView to receive an image * @param value the value retrieved from the data set * * @see #setViewImage(ImageView, String) */ public void setViewImage(ImageView v, int value) {
v.setImageResource(value);
}
public void setImageBitmap(ImageView v, Bitmap value) {
v.setImageBitmap(value);
}
/** * Called by bindView() to set the image for an ImageView but only if * there is no existing ViewBinder or if the existing ViewBinder cannot * handle binding to an ImageView. * * By default, the value will be treated as an image resource. If the * value cannot be used as an image resource, the value is used as an * image Uri. * * This method is called instead of {@link #setViewImage(ImageView, int)} * if the supplied data is not an int or Integer. * * @param v ImageView to receive an image * @param value the value retrieved from the data set * * @see #setViewImage(ImageView, int) */ public void setViewImage(ImageView v, String value) {
try {
v.setImageResource(Integer.parseInt(value));
} catch (NumberFormatException nfe) {
v.setImageURI(Uri.parse(value));
}
}
/** * Called by bindView() to set the text for a TextView but only if * there is no existing ViewBinder or if the existing ViewBinder cannot * handle binding to an TextView. * * @param v TextView to receive text * @param text the text to be set for the TextView */ public void setViewText(TextView v, String text) {
// v.setText(Html.fromHtml(text)); v.setText(text);
}
public Filter getFilter() {
if (mFilter == null) {
mFilter = new SimpleFilter();
}
return mFilter;
}
/** * This class can be used by external clients of SimpleAdapter to bind * values to views. * * You should use this class to bind values to views that are not * directly supported by SimpleAdapter or to change the way binding * occurs for views supported by SimpleAdapter. * * @see MySimpleAdapter#setViewImage(ImageView, int) * @see MySimpleAdapter#setViewImage(ImageView, String) * @see MySimpleAdapter#setViewText(TextView, String) */ public static interface ViewBinder {
/** * Binds the specified data to the specified view. * * When binding is handled by this ViewBinder, this method must return true. * If this method returns false, SimpleAdapter will attempts to handle * the binding on its own. * * @param view the view to bind the data to * @param data the data to bind to the view * @param textRepresentation a safe String representation of the supplied data: * it is either the result of data.toString() or an empty String but it * is never null * * @return true if the data was bound to the view, false otherwise */ boolean setViewValue(View view, Object data, String textRepresentation);
}
/** * <p>An array filters constrains the content of the array adapter with * a prefix. Each item that does not start with the supplied prefix * is removed from the list.</p>
*/ private class SimpleFilter extends Filter {
@Override protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mUnfilteredData == null) {
mUnfilteredData = new ArrayList<Map<String, ?>>(mData);
}
if (prefix == null || prefix.length() == 0) {
ArrayList<Map<String, ?>> list = mUnfilteredData;
results.values = list;
results.count = list.size();
} else {
String prefixString = prefix.toString().toLowerCase();
ArrayList<Map<String, ?>> unfilteredValues = mUnfilteredData;
int count = unfilteredValues.size();
ArrayList<Map<String, ?>> newValues = new ArrayList<Map<String, ?>>(count);
for (int i = 0; i < count; i++) {
Map<String, ?> h = unfilteredValues.get(i);
if (h != null) {
int len = mTo.length;
for (int j=0; j<len; j++) {
String str = (String)h.get(mFrom[j]);
String[] words = str.split(" ");
int wordCount = words.length;
for (int k = 0; k < wordCount; k++) {
String word = words[k];
if (word.toLowerCase().startsWith(prefixString)) {
newValues.add(h);
break;
}
}
}
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
@Override protected void publishResults(CharSequence constraint, FilterResults results) {
//noinspection unchecked mData = (List<Map<String, ?>>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}
上面圖示我們想加入 listview 的
而 json 格式 是這樣
{
error: 0,
plan: [
{
plan_id: "2",
location: {
lat: "25.03307782031963",
lon: "121.56347179334261"
},
title: "東區小吃吃翻天",
banner: "http://ur-dev.hxcld.com/pub/ae7b7d33728d14fc1b9be8f837e6cac077e87582.jpg",
loc_type: 0,
shop: [
{
shop_id: "14496550138283",
shop_name: "亂來",
shop_en_name: "",
pic_link: "http://ur-dev.hxcld.com/pub/c9819577933c737e18c0a6e391d9ed2d576b7b34.png"
}
]
},
{
plan_id: "3",
location: {
lat: "25.03336556230476",
lon: "121.55261421190517"
},
title: "聯誼最佳場所",
banner: "http://ur-dev.hxcld.com/pub/10555193582edbed3c7fc9abd3119f7366bb5da67956263edb.png",
loc_type: 0,
shop: [
{
shop_id: "14437751117416",
shop_name: "台北三創店ABc",
shop_en_name: "Gt",
pic_link: "http://ur-dev.hxcld.com/pub/83bab64657b1cd6e9a31385cb564d5023ba934d7.png"
},
{
shop_id: "14437751177423",
shop_name: "中山林森北加盟服務中心",
shop_en_name: "Gt",
pic_link: "http://ur-dev.hxcld.com/pub/83bab64657b1cd6e9a31385cb564d5023ba934d7.png"
},
{
shop_id: "14437751177424",
shop_name: "內湖金湖加盟服務中心",
shop_en_name: "Gt",
pic_link: "http://ur-dev.hxcld.com/pub/83bab64657b1cd6e9a31385cb564d5023ba934d7.png"
}
]
}
]
}
所以我們轉 格式是這種型態 才能轉
public class PlanListObj {
public static final String KEY_ID = "id";
public static final String KEY_JSON = "json";
public Plan[] plan;
public String error;
public class Plan implements Comparable<Plan>{
public Shop[] shop;
public String title;
public Location location;
public String banner;
public String plan_id;
public int shopKm;
public int pub_en;
public int loc_type; //1:不分, 2:特定區域, 3:特定iBeacon public GtLocationObj.loc_pt[] loc_pt; // loc_type=2 才有
@Override public int compareTo(Plan another) {
return this.shopKm - another.shopKm;
}
// @Override// public DataType dataType() {// return DataType.Plan;// }//// @Override// public String uniqueID() {// return plan_id;// }////// public boolean isOutOfDate() {//// return (System.currentTimeMillis() - pub_en * 1000) > 0;//// }
}
public class Shop {
public String shop_id;
public String pic_link;
public String shop_en_name;
public String shop_name;
}
public class Location {
public String lon;
public String lat;
}
}
完成上面步驟之後
就可以開始刻layout
new Thread(){
@Override public void run() {
planListObj = GtRequestApi.getPlanList(IndexActivity.this);
if(planListObj.plan!=null &&planListObj.plan.length!=0){
// try {// Thread.sleep(2000);// } catch (InterruptedException e) {// e.printStackTrace();// }
runOnUiThread(new Runnable() {
@Override public void run() {
MySimpleAdapter mSimpleAdapter;
mListView = (ListView) findViewById(R.id.ur_index_list);
mListView.setDividerHeight(0);
mListView.setDivider(null);
storelist = new ArrayList<HashMap<String, Object>>();
mSimpleAdapter = new MySimpleAdapter(IndexActivity.this, storelist, storeResouce, storeform, storeto);
mListView.setAdapter(mSimpleAdapter);
//POI List for (final PlanListObj.Plan plan : planListObj.plan) {
float listdistance = 0;
if (mGooglelat != null && mGooglelon != null) {
Location crntLocation = new Location("");
crntLocation.setLatitude(Double.parseDouble(mGooglelat));
crntLocation.setLongitude(Double.parseDouble(mGooglelon));
Location newLocation = new Location("");
newLocation.setLatitude(Double.parseDouble(plan.location.lat));
newLocation.setLongitude(Double.parseDouble(plan.location.lon));
listdistance = crntLocation.distanceTo(newLocation); // in m// listdistance = listdistance / 1000;//km plan.shopKm = (int) listdistance;
// obj.urKm= new DecimalFormat("0.0").format(listdistance);
}
Arrays.sort(planListObj.plan);
Log.d("Jack","開始");
boolean isNotify = GtSharedPreferences.getPlanIsNotifyById(IndexActivity.this, plan.plan_id);
Log.d("Jack",isNotify+"");
Log.d("Jack",plan.loc_type+"");
if(plan.loc_type==2){
if (!isNotify) {
new Thread(){
@Override public void run() {
Gson gson = new Gson();
GtSharedPreferences.savePlanContentById(IndexActivity.this, plan.plan_id, gson.toJson(plan));
int order = 0;
for (GtLocationObj.loc_pt loc : plan.loc_pt) {
loc.pub_en = plan.pub_en;
loc.plan_id = plan.plan_id;
loc.tittle = plan.title;
loc.geoNum = order;
String id = gson.toJson(loc);
Log.d("Jack","id"+id);
Geofence.addRegion(IndexActivity.this, new Region(loc.lat, loc.lon, loc.radius, id, Region.FENCE_IN));
Log.d("Jack","註冊完成");
order++;
}
}
}.start();
}
}
HashMap<String, Object> hm = addData(plan);
storelist.add(hm);
}
// for (PlanListObj.Plan plan : planListObj.plan) {////// } progressDialog.dismiss();
if (isCencel) return;
}
});
}
}
}.start();
private HashMap<String, Object> addData(final PlanListObj.Plan plan) {
HashMap<String, Object> hm = new HashMap<String, Object>();
int index = 0;
String [] arrayLayout ={
KEY_STORE_LAYOUT,
KEY_STORE_LAYOUT_2,
KEY_STORE_LAYOUT_3,
KEY_STORE_LAYOUT_4,
KEY_STORE_LAYOUT_5
};
String[] arrayImg = {
KEY_STORE_IMG,
KEY_STORE_IMG_2,
KEY_STORE_IMG_3,
KEY_STORE_IMG_4,
KEY_STORE_IMG_5 };
String[] arrayName = {
KEY_STORE_NAME,
KEY_STORE_NAME_2,
KEY_STORE_NAME_3,
KEY_STORE_NAME_4,
KEY_STORE_NAME_5 };
final String[] arrayEngName = {
KEY_STORE_ENG_NAME,
KEY_STORE_ENG_NAM_2,
KEY_STORE_ENG_NAM_3,
KEY_STORE_ENG_NAM_4,
KEY_STORE_ENG_NAM_5 };
class StoreOnClickListener implements OnClickListener{
private String mId;
public StoreOnClickListener(String id) {
mId = id;
}
@Override public void onClick(View v) {
showStoreDetail(mId);
}
}
final OnClickListener clickListener = new OnClickListener() {
@Override public void onClick(View v) {
Toast.makeText(IndexActivity.this,"轉跳企劃內頁",Toast.LENGTH_SHORT).show();
}
};
for (PlanListObj.Shop shop :plan.shop){
CustomImageLoader shoppic = new CustomImageLoader(shop.pic_link);
hm.put(arrayImg[index], shoppic);
hm.put(arrayName[index], shop.shop_name);
hm.put(arrayEngName[index], shop.shop_en_name);
StoreOnClickListener storeOnClickListener =new StoreOnClickListener(shop.shop_id);
hm.put(arrayLayout[index], "View.VISIBLE");
hm.put(arrayLayout[index], storeOnClickListener);
index++;
}
這邊是因為 我們要一層一層去拆開 之後塞進去 但因為我們layout 刻死的
所以就要用index 方式 加入layout
不可以寫成 hm.put(KEY_STORE_NAME,, shop.shop_en_name);
這樣都會塞成同筆資料
for(int i = index; i<5; i++) {
hm.put(arrayLayout[index], "View.GONE");
}
CustomImageLoader mCustomImageLoader = new CustomImageLoader(plan.banner);
hm.put(KEY_STORE_TITTLE, plan.title);
hm.put(KEY_STORE_BANNER,mCustomImageLoader);
hm.put(KEY_STORE_BANNER_jump,clickListener);
hm.put(KEY_STORE_MORE,clickListener);
return hm;
}