I have a piece of code with int array hard coded, this works correctly.
But now I want to move it to an external ressource file and take images from there.
I already used the same for string array, to move hard code and use ressources, it works (see commented lines), but for int I don't have any errors but also don't have any images in app (see commented lines).
Here is my int array format:
<integer-array name="mImageIds1">
<item>#drawable/ic_android_black_24dp</item>
<item>#drawable/ic_android_black_24dp</item>
<item>#drawable/ic_android_black_24dp</item>
What's wrong?
public class MainActivity extends ListActivity {
private String[] mText = {"First", "Second", "Third", "Fourth", "Fifth", "Sixth",
"Seventh", "Eighth", "Ninth", "Tenth", "Eleventh", "Twelfth"};
int[] mImageIds = {R.drawable.ic_android_black_24dp, R.drawable.ic_android_blue_24dp,
R.drawable.ic_android_black_24dp, R.drawable.ic_android_blue_24dp...
};
private myAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new myAdapter(this);
setListAdapter(mAdapter);
}
private class myAdapter extends BaseAdapter {
private LayoutInflater mLayoutInflater;
myAdapter(Context context) {
mLayoutInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return mText.length;
}
#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 = mLayoutInflater.inflate(R.layout.activity_main, null);
int[] mArrayImageIds=getResources().getIntArray(R.array.mImageIds1);
ImageView image = (ImageView) convertView.findViewById(R.id.imageViewIcon);
if (1==1)
image.setImageResource( mArrayImageIds[position]);
// image.setImageResource( mImageIds[position]);
TextView signTextView = (TextView) convertView.findViewById(R.id.textViewSign);
signTextView.setText(mText[position]);
String[] zooString=getResources().getStringArray(R.array.text1);
TextView dateTextView = (TextView) convertView.findViewById(R.id.textViewDate);
//dateTextView.setText(mSignatures[position]);
dateTextView.setText(zooString[position]);
return convertView;
}
String getString(int position) {
return mText[position] + " (" + mSignatures[position] + ")";
}
}
}
I think TypedArray is what you are looking for. I have samples using it. If you are interested, take a look at codes below:
TypedArray tArray = getResources().obtainTypedArray(R.array.frag_home_ids);
int count = tArray.length();
int[] mArrayImageIds = new int[count];
for (int i = 0; i < mArrayImageIds .length; i++) {
mArrayImageIds[i] = tArray.getResourceId(i, 0);
}
//Recycles the TypedArray, to be re-used by a later caller.
//After calling this function you must not ever touch the typed array again.
tArray.recycle();
Related
Here's my code, please help check my problem
My string list that has the same name with the images in res drawable:
<resources>
<string name="app_name">Intent Practice 1</string>
<string-array name="list_name">
<item>akiza</item>
<item>blueeyes</item>
<item>buster</item>
<item>cyberdragon</item>
<item>darklaw</item>
<item>darkmagician</item>
<item>darkmagiciangirl</item>
<item>darkpaladin</item>
<item>dragunity</item>
<item>exodia</item>
<item>gaia</item>
<item>galaxyeyes</item>
<item>harpies</item>
<item>hope</item>
<item>joey</item>
<item>junk</item>
<item>kaibaseto</item>
<item>marik</item>
<item>neos</item>
<item>redeyes</item>
<item>shaddoll</item>
<item>shiningflare</item>
<item>skulled</item>
<item>spear</item>
<item>stardust</item>
<item>tourguide</item>
<item>wingeddragon</item>
<item>yamiyugi</item>
<item>yudai</item>
<item>yugimuto</item>
<item>yuma</item>
<item>yusei</item>
<item>question</item>
</string-array>
</resources>
I can set an ImageView using
ImageView imgQuestion, imgAnswer, temp;
static ArrayList<String> arrayName;
public static ArrayList<HinhAnh> arrayImg;
String questionName;
int REQUEST_CODE_IMG = 2703;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imgAnswer = findViewById(R.id.imgAnswer);
imgQuestion = findViewById(R.id.imgQuestion);
String[] mangTen = getResources().getStringArray(R.array.list_name);
arrayName = new ArrayList<>(Arrays.asList(mangTen));
arrayImg = new ArrayList<>();
Collections.shuffle(arrayName);
**int idImg = getResources().getIdentifier(arrayName.get(1), "drawable", getPackageName());
imgQuestion.setImageResource(idImg);**
But I dont know how to add the list of images in to the arrayImg, I used:
for (int position = 0; position < arrayName.size(); position++){
int id = getResources().getIdentifier(arrayName.get(position), "drawable", getPackageName());
arrayImg.add(new HinhAnh(arrayName.get(position) + "", id));
Toast.makeText(this, arrayImg.get(1).getTen() + "", Toast.LENGTH_SHORT).show();
}
I used Toast to check if I add successfully then the error showed out
Caused by: java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.get(ArrayList.java:437)
at com.example.intentpractice.MainActivity.onCreate(MainActivity.java:38)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
My class HinhAnh
public class HinhAnh {
private String Ten;
private int Hinh;
public HinhAnh(String ten, int hinh) {
Ten = ten;
Hinh = hinh;
}
public String getTen() {
return Ten;
}
public void setTen(String ten) {
Ten = ten;
}
public int getHinh() {
return Hinh;
}
public void setHinh(int hinh) {
Hinh = hinh;
}
}
They all lead to my adapter is null then I cannot fill my gridview at all. Please help!!
Edit:
I changed the line to get(position) then it worked. But it still showed error point to my adapter, here's my adapter:
public class ImageAdapter extends BaseAdapter {
private Context context;
private int layout;
private List<HinhAnh> imageList;
public ImageAdapter(Context context, int layout, List<HinhAnh> imageList) {
this.context = context;
this.layout = layout;
this.imageList = imageList;
}
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
private class ViewHolder{
ImageView imgHinh;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null){
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(layout, null);
holder.imgHinh = convertView.findViewById(R.id.imgItem);
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
holder.imgHinh.setImageResource(imageList.get(position).getHinh());
return convertView;
}
}
and where I called it
adapter = new ImageAdapter(this, R.layout.imageline, MainActivity.arrayImg);
gridView.setAdapter(adapter);
The error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.GridView.setAdapter(android.widget.ListAdapter)' on a null object reference
at com.example.intentpractice.Answers.onCreate(Answers.java:18)
Solved, I forgot returning getCount to array.size().
Thanks all!!!
There is a issue in your for loop for adding the images into the list.
For the position 0, there will be only one element in the arrayImg but you are calling arrayImg.get(1) which is causing java.lang.IndexOutOfBoundsException
change that line to:
for (int position = 0; position < arrayName.size(); position++){
int id = getResources().getIdentifier(arrayName.get(position), "drawable", getPackageName());
arrayImg.add(new HinhAnh(arrayName.get(position) + "", id));
Toast.makeText(this, arrayImg.get(position).getTen() + "", Toast.LENGTH_SHORT).show();
}
I would like to ask some question about AdapterView.
In my application, there is an activity which retrieve data from database and display them in AdapterView.
However, when i install the application in different devices, I found that the part I have just mentioned could only function on some devices. The others cannot show the database results.
Here is my code:
private void showResults(String query) {
Cursor cursor = searchCustByInputText(query);
if (cursor == null) {
//
} else {
// Specify the columns we want to display in the result
String[] from = new String[] {
"cust_code",
"chinese_name"};
// Specify the Corresponding layout elements where we want the columns to go
int[] to = new int[] {
R.id.scust_code,
R.id.schinese_name};
// Create a simple cursor adapter for the definitions and apply them to the ListView
SimpleCursorAdapter customers = new SimpleCursorAdapter(this,R.layout.cust_list_item, cursor, from, to);
mListView.setAdapter(customers);
// Define the on-click listener for the list items
mListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor c = (Cursor) mListView.getItemAtPosition(position);
String cust_code = c.getString(c.getColumnIndex("cust_code"));
if (callFromAct.equals("Main")) {
String pay_term = c.getString(c.getColumnIndex("pay_term"));
String chinese_name = c.getString(c.getColumnIndex("chinese_name"));
String english_name = c.getString(c.getColumnIndex("english_name"));
String address_1 = c.getString(c.getColumnIndex("address_1"));
String address_2 = c.getString(c.getColumnIndex("address_2"));
String address_3 = c.getString(c.getColumnIndex("address_3"));
String address_4 = c.getString(c.getColumnIndex("address_4"));
String contact = c.getString(c.getColumnIndex("contact"));
String telephone = c.getString(c.getColumnIndex("telephone"));
String last_order_date = c.getString(c.getColumnIndex("last_order_date"));
//Pass data to another Activity
Intent it = new Intent(CustEnqActivity.this, CustEnqDetailsActivity.class);
Bundle bundle = new Bundle();
bundle.putString("cust_code", cust_code);
bundle.putString("pay_term", pay_term);
bundle.putString("chinese_name", chinese_name);
bundle.putString("english_name", english_name);
bundle.putString("address_1", address_1);
bundle.putString("address_2", address_2);
bundle.putString("address_3", address_3);
bundle.putString("address_4", address_4);
bundle.putString("contact", contact);
bundle.putString("telephone", telephone);
bundle.putString("last_order_date", last_order_date);
it.putExtras(bundle);
startActivity(it);
}
else {
returnToCallingAct(cust_code);
}
//searchView.setQuery("",true);
}
});
}
}
Besides, I discovered there were two warnings in my logcat.
The constructor SimpleCursorAdapter(Context, int, Cursor, String[], int[]) is deprecated
AdapterView is a raw type. References to generic type AdapterView should be parameterized
Are they related to the problem?
Try to create a class that extends BaseAdapter and use ViewHolders for performance
eg:
public class MyBaseAdapter extends BaseAdapter {
ArrayList<ListData> myList = new ArrayList<ListData>();
LayoutInflater inflater;
Context context;
public MyBaseAdapter(Context context, ArrayList<ListData> myList) {
this.myList = myList;
this.context = context;
inflater = LayoutInflater.from(this.context); // only context can also be used
}
#Override
public int getCount() {
return myList.size();
}
#Override
public ListData getItem(int position) {
return myList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
MyViewHolder mViewHolder;
if(convertView == null) {
convertView = inflater.inflate(R.layout.layout_list_item, null);
mViewHolder = new MyViewHolder();
convertView.setTag(mViewHolder);
} else {
mViewHolder = (MyViewHolder) convertView.getTag();
}
mViewHolder.tvTitle = detail(convertView, R.id.tvTitle, myList.get(position).getTitle());
mViewHolder.tvDesc = detail(convertView, R.id.tvDesc, myList.get(position).getDescription());
mViewHolder.ivIcon = detail(convertView, R.id.ivIcon, myList.get(position).getImgResId());
return convertView;
}
// or you can try better way
private TextView detail(View v, int resId, String text) {
TextView tv = (TextView) v.findViewById(resId);
tv.setText(text);
return tv;
}
private ImageView detail(View v, int resId, int icon) {
ImageView iv = (ImageView) v.findViewById(resId);
iv.setImageResource(icon); //
return iv;
}
private class MyViewHolder {
TextView tvTitle, tvDesc;
ImageView ivIcon;
}
}
More info/example:
http://www.pcsalt.com/android/listview-using-baseadapter-android/#sthash.lNGSCiyB.dpbs
I have 3 arraylist that i have combined to show in listview. Wehen i click on to generate listview, it works fine the first time but when i hit back and then click the button again, the listview shows nothing. Not sure what is cause it. I checked other post but couldnt find an answer. I am not too good with Arraylist so any details would be greatly appreciated.
I have also noticed this message in Log cat. not sure what it means.
onVisibilityChanged() is called, visibility : 0
public class Edit extends Activity implements OnItemClickListener {
private int pic;
public String filename ="User Info";
//Declaring SHareddPreference as userprofile
static SharedPreferences userprofile;
ListView listView;
List<RowItem> rowItems;
// String[] titles, descriptions;
File imgpath=null;
Context context=this;
CustomListAdapter adapter;
private List<String> Titles = new ArrayList<String>();
private List<String> Actions = new ArrayList<String>();
private List<Bitmap> Images = new ArrayList<Bitmap>();
int x;
int y=1;
int z=1;
static int a=1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.aname);
listView = (ListView)findViewById(R.id.listing);
userprofile = getSharedPreferences(filename,0);
Intent pdf=getIntent();
pic= userprofile.getInt("lastpic",pic);
x=pic;
Log.d("editpic",new Integer(pic).toString());
while(y!=x){
String comment = commentresult();
Titles.add(comment);
y++;
Log.d("y",new Integer(y).toString());
}
while(z!=x){
String act = actionresult();
Actions.add(act);
z++;
Log.d("z",new Integer(z).toString());}
while(a!=x){
Bitmap photo = getbitmap();
Images.add(photo);
a++;
Log.d("a",new Integer(a).toString());}
Titles.toArray();
Actions.toArray();
Images.toArray();
rowItems = new ArrayList<RowItem>();
for (int i = 0; i < Images.size(); i++) {
RowItem item = new RowItem(Images.get(i), Titles.get(i),Actions.get(i));
rowItems.add(item);
}
Log.d("TAG", "listview null? " + (listView == null));
CustomListAdapter adapter = new CustomListAdapter(this,
R.layout.aname_list_item, rowItems);
Log.d("TAG", "adapter=null? " + (adapter == null));
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
listView.setOnItemClickListener(this);
}
public static Bitmap getbitmap() {
String photo1 =userprofile.getString("picpath"+a, "");
File imgpath=new File(photo1);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap bmp=DecodeImage.decodeFile(imgpath, 800, 1000, true);
bmp.compress(Bitmap.CompressFormat.JPEG, 100 , stream);
Bitmap photo2=bmp;
return photo2;
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast toast = Toast.makeText(getApplicationContext(),
"Item " + (position + 1) + ": " + rowItems.get(position),
Toast.LENGTH_SHORT);
toast.setGravity(Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0);
toast.show();
}
public String commentresult()
{
// String com2 = null;
// while(y!=x){
String comment=userprofile.getString("comment"+y, "");
String com1=comment;
String com2=com1;
// }
return com2;
}
public String actionresult()
{
// String act2 = null;
// while(y!=x){
String action=userprofile.getString("action"+z, "");
String act1=action;
String act2=act1;
// }
return act2;
}
private static final long delay = 2000L;
private boolean mRecentlyBackPressed = false;
private Handler mExitHandler = new Handler();
private Runnable mExitRunnable = new Runnable() {
#Override
public void run() {
mRecentlyBackPressed=false;
}
};
#Override
public void onBackPressed() {
//You may also add condition if (doubleBackToExitPressedOnce || fragmentManager.getBackStackEntryCount() != 0) // in case of Fragment-based add
if (mRecentlyBackPressed) {
mExitHandler.removeCallbacks(mExitRunnable);
mExitHandler = null;
super.onBackPressed();
}
else
{
mRecentlyBackPressed = true;
Toast.makeText(this, "press again to exit", Toast.LENGTH_SHORT).show();
mExitHandler.postDelayed(mExitRunnable, delay);
}
}
#Override
public void onDestroy() {
// Destroy the AdView.
super.onDestroy();
}
Custom List Adapter:
public class CustomListAdapter extends ArrayAdapter<RowItem> {
Context context;
List<RowItem> items;
public CustomListAdapter(Context context, int resourceId,
List<RowItem> items) {
super(context, resourceId, items);
this.context = context;
this.items = items;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
#Override
public RowItem getItem(int position) {
// TODO Auto-generated method stub
return items.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
/*private view holder class*/
private class ViewHolder {
ImageView imageView;
TextView txtTitle;
TextView txtDesc;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
RowItem rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.aname_list_item, null);
holder = new ViewHolder();
holder.txtDesc = (TextView) convertView.findViewById(R.id.desc);
holder.txtTitle = (TextView) convertView.findViewById(R.id.rab);
holder.imageView = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
// String name=items.get(position).getDesc();
holder.txtDesc.setText(rowItem.getDesc());
holder.txtTitle.setText(rowItem.getTitle());
holder.imageView.setImageBitmap(rowItem.getImageId());
// holder.imageView.setImageResource(Images.get(position) .getPlaceholderleft());
return convertView;
}
}
It looks like this is because you've made your variables x, y, z and a all static, which means there is a single instance of the variables shared by all instances of the class. Therefore, when you call onCreate the second time, all your while loop termination conditions are already met, so the while loops never execute. It's unclear to me why you've made these static, so unless you need them to be, you should remove the static keyword for these variables.
Why are you creating another object of ListView in onCreate() and onResume()
Remove code from onResume()
Also replace this line in onCreate()
old line ListView listView = (ListView)findViewById(R.id.listing);
New line listView = (ListView)findViewById(R.id.listing);
I have different integer array of drawables like this:
Integer[] imagesR = {
R.drawable.albacoretuna, R.drawable.almonds
};
Integer[] imagesACE = {
R.drawable.captopril, R.drawable.lisinopril, R.drawable.vasotec
};
Each integer array should only display which is based on user's click.
Below is what I have tried:
Gallery gallery = (Gallery) findViewById (R.id.gallery3);
Bundle extras = getIntent().getExtras();
if (extras != null) {
String value = extras.getString("medication");
if( value.equals("Angiotensin II Receptor Blockers") ){
header.setText("Angiotensin II Receptor Blockers");
note.setText(R.string.receptorblockers);
gallery.setAdapter(new ImageAdapter.IMAGE_SET_ONE);
}
else if( value.equals("Angiotensin Converting Enzyme (ACE) Inhibitors") ){
header.setText("Angiotensin Converting Enzyme (ACE) Inhibitors");
note.setText(R.string.aceinhibitorsdescription);
}
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
Integer[] mImageIds = {
};
public ImageAdapter(Context c) {
mContext = c;
TypedArray a = obtainStyledAttributes(R.styleable.HelloGallery);
// mGalleryItemBackground = a.getResourceId(
// R.styleable.HelloGallery_android_galleryItemBackground, 0);
a.recycle();
}
public ImageAdapter(Context c,Integer gallery[]) {
mContext = c;
mImageIds=gallery;
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public static final int IMAGE_SET_ONE = 1;
public static final int IMAGE_SET_TWO = 2;
private int mImageSet;
public void setImageSet(int imageSet) {
mImageSet = imageSet;
}
public View getView(int pos, View convertView, ViewGroup arg2) {
ImageView i;
//= new ImageView(mContext);
if (convertView == null) { // if it's not recycled, initialize some attributes
i = new ImageView(mContext);
i.setLayoutParams(new GridView.LayoutParams(85, 85));
i.setScaleType(ImageView.ScaleType.CENTER_CROP);
i.setPadding(8, 8, 8, 8);
} else {
i = (ImageView) convertView;
}
if(mImageSet == IMAGE_SET_ONE) {
// load the correct image in...
Integer[] imagesACE = {
R.drawable.captopril, R.drawable.lisinopril, R.drawable.vasotec
};
i.setImageResource(imagesACE[pos]);
} else if(mImageSet == IMAGE_SET_TWO) {
// load the correct image in...
Integer[] imagesR = {
R.drawable.albacoretuna, R.drawable.almonds
};
i.setImageResource(imagesR[pos]);
}
//i.setImageResource(mImageIds[arg0]);
return i;
}
}
But I can't seem to figure out how to accomplish this correctly. Has anybody already tried something like this? Can you help me finish this? I'd appreciate your help. Thanks.
1) change the constructor of your ImageAdapter to be like this :
public ImageAdapter(Context c,int imageSet) {
this.mContext = c;
this.mImageSet=imageSet;
}
2) and when you try to set the adapter to your Gallery instance , use this code :
//case to display drawables in array1
gallery.setAdapter(new ImageAdapter(YourActivity.this, ImageAdapter.IMAGE_SET_ONE));
//case to display drawables in array2
gallery.setAdapter(new ImageAdapter(YourActivity.this, ImageAdapter.IMAGE_SET_TWO));
I have a very strange problem while using my ListView.
Only a part of my adapter items are renderd in the listview on screen but when I interact with the listview (ie tries to scroll it) all items are renderd properly.
This fenonemon only occurs if i have less items than the screen can show. Take a look at these screenshots below.
Before interaction:
After interaction:
Source code of activity where adding items:
String[] jRests = getResources().getStringArray(R.array.j_restaurants);
String[] lRests = getResources().getStringArray(R.array.l_restaurants);
items = new ArrayList<Object>();
items.add(getString(R.string.campus_j));
for(String item : jRests){
String[] val = item.split(",,,");
items.add(new FoodSectionListItem(new Restaurant(val[0], val[1], val[2], "")));
}
items.add(getString(R.string.campus_l));
for(String item : lRests){
String[] val = item.split(",,,");
items.add(new FoodSectionListItem(new Restaurant(val[0], val[1], val[2], "")));
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
adapter = new BaseSectionAdapter(this, R.layout.list_item_fragment_header);
if(!isTabletView()){
adapter.setSelectedItem(-1);
}
adapter.setItems(items);
Code of adapter:
public class BaseSectionAdapter extends AmazingAdapter {
private LayoutInflater inflater;
private int selectedItem = 0;
private List<Object> items;
private List<SectionItem> sections = new ArrayList<SectionItem>(10);
private List<Class> itemTypes = new ArrayList<Class>();
private List<Integer> sectionPositions = new ArrayList<Integer>();
private int listHeaderLayoutId;
private View headerView;
public static interface ISectionListItem {
public void setProps(View convertView, int position, int selectedItem);
public View getLayout(LayoutInflater inflater);
}
private class SectionItem implements Serializable {
private static final long serialVersionUID = -8930010937740160935L;
String text;
int position;
public SectionItem(String text, int position) {
this.text = text;
this.position = position;
}
}
public BaseSectionAdapter(Context context, int listHeaderLayoutId) {
this.listHeaderLayoutId = listHeaderLayoutId;
init(context);
}
public BaseSectionAdapter(Context context, int listHeaderLayoutId, List<Object> listItems) {
this.listHeaderLayoutId = listHeaderLayoutId;
init(context);
initListItems(listItems);
}
private void init(Context context) {
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setSelectedItem(int position) {
selectedItem = position;
}
// public List<ListItem> getItems() {
// return items;
// }
private void initListItems(List<Object> itemList) {
int curSection = -1;
//int curPosition = 0;
//curSection = 0;
this.items = itemList;
itemTypes.clear();
sections.clear();
sectionPositions.clear();
int listSize = itemList.size();
for(int i = 0; i < listSize; i++){
Object currentItem = items.get(i);
if(currentItem instanceof String){
sections.add(new SectionItem((String) currentItem,i));
curSection++;
}
if(!itemTypes.contains(currentItem.getClass())){
itemTypes.add(currentItem.getClass());
}
sectionPositions.add(curSection);
}
Log.d("test", "No of items = "+items.size());
Log.d("test", "No of itemtypes = "+itemTypes.size());
Log.d("test", "View type count = "+getViewTypeCount());
}
public void setItems(List<Object> itemList) {
initListItems(itemList);
}
public int getCount() {
return items==null?0:items.size();
}
#Override
public int getViewTypeCount(){
return (itemTypes.size() == 0)?1:itemTypes.size();
}
#Override
public int getItemViewType(int position){
return itemTypes.indexOf(items.get(position).getClass());
}
#Override
public boolean isEnabled(int position){
return !(items.get(position) instanceof String || items.get(position) instanceof EmptySectionListItem);
}
#Override
public Object getItem(int position) {
return items.get(position);
}
public long getItemId(int position) {
return position;
}
#Override
protected void onNextPageRequested(int page) {
// TODO Auto-generated method stub
}
#Override
protected void bindSectionHeader(View view, int position,
boolean displaySectionHeader) {
// TextView lSectionTitle = (TextView) view
// .findViewById(R.id.txt_list_header);
// if (displaySectionHeader) {
// lSectionTitle.setVisibility(View.VISIBLE);
// lSectionTitle
// .setText(getSections()[getSectionForPosition(position)]);
// } else {
// lSectionTitle.setVisibility(View.GONE);
// }
}
#Override
public View getAmazingView(int position, View convertView, ViewGroup parent) {
Object curItemObject = items.get(position);
boolean isHeader = (curItemObject instanceof String);
if(convertView == null){
if(isHeader && headerView != null){
convertView = headerView;
}else if(isHeader){
convertView = inflater.inflate(listHeaderLayoutId, null);
headerView = convertView;
}else{
convertView = ((ISectionListItem) curItemObject).getLayout(inflater);
}
}
if(isHeader){
TextView header = ((TextView)convertView.findViewById(R.id.txt_list_header));
header.setText((String)curItemObject);
}else{
((ISectionListItem)curItemObject).setProps(convertView, position, selectedItem);
}
return convertView;
}
#Override
public void configurePinnedHeader(View header, int position, int alpha) {
TextView textView = ((TextView)header.findViewById(R.id.txt_list_header));
textView.setText(getSections()[getSectionForPosition(position)]);
}
#Override
public int getPositionForSection(int section) {
if(section >= sections.size()){
return 0;
}
return sections.get(section).position;
}
#Override
public int getSectionForPosition(int position) {
return sectionPositions.get(position);
}
#Override
public String[] getSections() {
String[] res = new String[sections.size()];
for (int i = 0; i < res.length; i++) {
res[i] = sections.get(i).text;
}
return res;
}
}
Code of layout:
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.HORIZONTAL);
FrameLayout listLayout = new FrameLayout(this);
LinearLayout.LayoutParams listParams = new LinearLayout.LayoutParams(0, FrameLayout.LayoutParams.MATCH_PARENT);
listParams.weight = 1;
listLayout.setId(LIST_FRAGMENT_VIEW_ID);
FrameLayout detailLayout = new FrameLayout(this);
LinearLayout.LayoutParams detailParams = new LinearLayout.LayoutParams(0, FrameLayout.LayoutParams.MATCH_PARENT);
detailParams.weight = 2;
detailLayout.setId(DETAIL_FRAGMENT_VIEW_ID);
layout.addView(listLayout, listParams);
layout.addView(detailLayout, detailParams);
if(savedInstanceState == null){
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(listLayout.getId(), (Fragment) listFragment, TWO_PANEL_LIST_FRAGMENT_TAG);
ft.add(detailLayout.getId(), detailFragment);
ft.commit();
}
setContentView(layout);
try calling notifyDataSetChanged() in runOnUIThread() method like I have shown below and it will work like a charm. :)
runOnUiThread(new Runnable() {
#Override
public void run() {
messageAdapter.notifyDataSetChanged();
}
});
i dont know what causes the problem, but if you don't find a logical solution to it you could try something like this:
trigger an onTouchEvent() programmatically whenever you launch the ListView.
scroll down and back up programmatically as soon as the ListView is launched.
etc..
Add ListView widget to layout.xml and add content of list to that. Do not use FrameLayout as it probably is the cause of the problem. It is updating content after touch so the Layout it is on is no implementing the correct onCreate() setup as the ListView widget has.
Are you calling the method notifyDataSetChanged() on your adapter after adding new items? This causes the listview to refresh its view when the underlying dataset is changed.
If it still doesn't work, try notifyDataSetInvalidated() that causes the listview to redraw completely.
Solved it!!!
Problem was with the adapter trying to reuse the same section item. Not good!!!
Changed it to inflate the section item each time we hit a section!