Reputation: 77
I have a SherlockListFragment to display a list with certain information if is available on a fetched JSONObject. There are four types of information: phone, website, location and opening hours, and each one of those has its own "icon" to be displayed on the list. So, my problem is how to display custom layouts for each one of the types, and also how can I add and delete items from the list programmatically. Thanks in advance
Upvotes: 0
Views: 410
Reputation: 50538
Create interface (or abstract class), lets say:
public interface DataType{
public MyType getType(); //where MyType is my some enum.
}
public enum MyType { TYPE_1(R.layout.layout1), TYPE_2(R.layout.layout2), TYPE_3(R.layout.layout3)
private resourceId;
MyType(int resource){
resourceId = resource;
}
public getResourceLayout(){
return resourceId;
}
};
In your class implement this interface like:
public class MyData1 implement DataType{
//...
@Override
public MyType getType(){
return TYPE_1
}
}
public class MyData2 implement DataType{
//...
@Override
public MyType getType(){
return TYPE_2
}
}
etc...
Make your adapter take objects of type DataType.
In your getView()
of your adapter decide which layout to inflate something like:
public View getView(..... ){
//.....
if(convertView==null){
convetView = mLayoutInflater.inflate(dataAtThatPosition.getResourceLayout(), null);
//.....
}
// use getType() to evaluate further actions if needed based on the type
}
Another approach is leaving interface/abstract class behind and decide which layout to inflate based on the assignation of the class. In that case your adapter will take generic type T, when deciding which layout to inflate you will have to do something like this in your getView():
public View getView(..... ){
T data = getItemAtPosition(position);
if(convertView==null){
convertView = mLayoutInflater.inflate((data.isAssignableFrom(MyData1.class)? R.layout.layout1 : data.isAssignableFrom(MyData2.class)? R.layout.layout1 : R.layout.layout3), null);
}
}
Personally I think the second approach is quite dirty. :)
I hope this gives you idea. :)
Upvotes: 1
Reputation: 2290
Your best bet would be to handle it in the getView(int, View, ViewGroup) method of your ListAdapter. If you construct the adapter with a context and JSONObjects (in an array or JSONArray) it's pretty simple using each JSONObjects' has(String) method to check which it is. Just inflate a different layout depending on which the object has.
The getView(int, View, ViewGroup) method in your Adapter:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
try {
jsonObject = json.getJSONObject(position);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (jsonObject.has("phone")) {
convertView = inflater.inflate(R.layout.list_item_phone, null);
TextView details = (TextView) convertView.findViewById(R.id.item_message);
details.setText(jsonObject.getString("phone"));
} else if (jsonObject.has("website")) {
convertView = inflater.inflate(R.layout.list_item_website, null);
TextView details = (TextView) convertView.findViewById(R.id.item_message);
details.setText(jsonObject.getString("phone"));
} else if (jsonObject.has("location")) {
convertView = inflater.inflate(R.layout.list_item_location, null);
TextView details = (TextView) convertView.findViewById(R.id.item_message);
details.setText(jsonObject.getString("phone"));
} else if (jsonObject.has("opening_hours")) {
convertView = inflater.inflate(R.layout.list_item_opening_hours, null);
TextView details = (TextView) convertView.findViewById(R.id.item_message);
details.setText(jsonObject.getString("phone"));
}
} catch (JSONException e) { e.printStackTrace(); }
return convertView;
}
You will probably want to do more in each if statement, like add click listeners or whatever... unless you have autoLink on your views. If you're relying on autoLink to resolve the clickability of the data then you wouldn't need to inflate different layouts, you could just use switch the icon instead.
@Override
public View getView(int position, View convertView, ViewGroup parent) {
try {
jsonObject = json.getJSONObject(position);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item, null);
((TextView) convertView.findViewById(R.id.item_message)).setAutoLinkMask(Linkify.ALL); //autoLink phone, address, etc.
}
ImageView icon = (ImageView) convertView.findViewById(R.id.item_type_icon);
if (jsonObject.has("phone")) {
icon.setImageResource(R.id.phone_icon);
} else if (jsonObject.has("website")) {
icon.setImageResource(R.id.website_icon);
} else if (jsonObject.has("location")) {
icon.setImageResource(R.id.location_icon);
} else if (jsonObject.has("opening_hours")) {
icon.setImageResource(R.id.opening_hours_icon);
}
} catch (JSONException e) { e.printStackTrace(); }
return convertView;
}
EDIT: Since it seems like you may need the separate views dynamically...
@Override
public View getView(int position, View convertView, ViewGroup parent) {
try {
jsonObject = json.getJSONObject(position);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item, null); //This should have a linear layout with icons and textview for each node...
}
if (jsonObject.has("phone")) {
LinearLayout phoneLayout = (LinearLayout) convertView.findViewById(R.id.phone_layout); //This layout should already have the appropriate icon in it //*/
phoneLayout.setVisibility(View.VISIBLE); //Necessary because the convert view doesn't guarantee what state this will be in as we've been modifiying them. //*/
((TextView) phoneLayout.findViewById(R.id.message)).setText(jsonObject.getString("phone"));
} else { ((LinearLayout) convertView.findViewById(R.id.phone_layout)).setVisibility(View.GONE); }
if (jsonObject.has("website")) {
LinearLayout websiteLayout = (LinearLayout) convertView.findViewById(R.id.website_layout);
websiteLayout.setVisibility(View.VISIBLE);
((TextView) websiteLayout.findViewById(R.id.message)).setText(jsonObject.getString("website"));
} else { ((LinearLayout) convertView.findViewById(R.id.website_layout)).setVisibility(View.GONE); }
if (jsonObject.has("location")) {
LinearLayout locationLayout = (LinearLayout) convertView.findViewById(R.id.location_layout);
locationLayout.setVisibility(View.VISIBLE);
((TextView) locationLayout.findViewById(R.id.message)).setText(jsonObject.getString("location"));
} else { ((LinearLayout) convertView.findViewById(R.id.location_layout)).setVisibility(View.GONE); }
if (jsonObject.has("opening_hours")) {
LinearLayout openingHoursLayout = (LinearLayout) convertView.findViewById(R.id.opening_hours_layout);
openingHoursLayout.setVisibility(View.VISIBLE);
((TextView) openingHoursLayout.findViewById(R.id.message)).setText(jsonObject.getString("opening_hours"));
} else { ((LinearLayout) convertView.findViewById(R.id.opening_hours_layout)).setVisibility(View.GONE); }
} catch (JSONException e) { e.printStackTrace(); }
return convertView;
}
list_item.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
<LinearLayout
android:id="@+id/phone_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_list_item_phone" />
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
<LinearLayout
android:id="@+id/website_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_list_item_website" />
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
<!-- ETC. A layout for each item. -->
</LinearLayout>
Upvotes: 0