Android: Binding Layout with Dynamic Sublayout (ViewHolder & SubViewHolder)
android, android-layout, android-view
Solution
The easiest way to achieve your goal is to add view for each attachment programmatically. You must do smth like this: make holder.newsAttachments - linearLayout, for example.
Then in your bindView method:
holder.newsAttachment.removeAllViews(); //remove views if it exists
while (newsAttachmentCursor.moveToNext()) {
View view = LayoutInflater.from(context).inflate(R.layout.layout_for_attachment, null);
//fill view
String fileName = newsAttachmentCursor.getString(newsAttachmentCursor.getColumnIndex(DatabaseHelper.NEWS_AT_NAME));
view.setTag(fileName); // add as tag something, what you need inside onCLickListener
((TextView) view.findViewById(R.id.attachment_view_name)).setText(fullName);
holder.newsAttachment.addView(view);
view.setOnClickListener(new OnClickListener() {
@Override
void onClick(View v) {
String fileName = (String) v.getTag();
//do what you want with file name, or anything what you've added to tag.
}
});
}
It's only example, but this idea will works fine for small amount of attachments.
Problem
I am parsing JSON from server to Android and storing data in SQLite in which i have two tables `news` and `news_attachment`. I have done code for displaying `news` and `news_attachment` in list but now i want to display multiple attachment for one news. The following code displaying last_attachment of the particular news. I want to display all attachment with Custom Layout which will be settle automatically in parent view. NewsAdapter.java ``` public class NewsAdapter extends SimpleCursorAdapter { DatabaseHelper dbHelper; LayoutInflater inflater; public NewsAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) { super(context, layout, c, from, to, flags); inflater = LayoutInflater.from(context); dbHelper = new DatabaseHelper(context); dbHelper.open(); } @Override public void bindView(View convertView, Context context, Cursor cursor) { ViewHolder holder = (ViewHolder) convertView.getTag(); if(cursor.isNull(cursor.getColumnIndex(DatabaseHelper.NEWS_TITLE))) { holder.newsTitleText.setVisibility(View.GONE); } else { holder.newsTitleText.setVisibility(View.VISIBLE); holder.newsTitleText.setText(""+cursor.getString(cursor.getColumnIndex(DatabaseHelper.NEWS_TITLE))); } if(cursor.isNull(cursor.getColumnIndex(DatabaseHelper.NEWS_TEXT))) { holder.newsText.setVisibility(View.GONE); } else { holder.newsText.setVisibility(View.VISIBLE); String newsText = cursor.getString(cursor.getColumnIndex(DatabaseHelper.NEWS_TEXT)); newsText = Html.fromHtml(newsText).toString(); holder.newsText.setText(newsText); } /*************************** * Getting Child Cursor... */ Cursor newsAttachmentCursor; int newsId; /** * Setting up values of news_Attachment Table... */ newsId = cursor.getInt(cursor.getColumnIndex(DatabaseHelper.NEWS_SERVER_ID)); newsAttachmentCursor = dbHelper.getNewsAttachment(newsId); /** * Displaying news Attachment */ if(newsAttachmentCursor.getCount() > 0 && newsAttachmentCursor != null){ newsAttachmentCursor.moveToFirst(); /** * Displaying NEWS_AT_NAME */ if(newsAttachmentCursor.isNull(newsAttachmentCursor.getColumnIndex(DatabaseHelper.NEWS_AT_NAME))) { holder.newsAttachment.setVisibility(View.GONE); } else{ holder.newsAttachment.setVisibility(View.VISIBLE); /** * Displaying If attachment has Images.... */ String fileName = newsAttachmentCursor.getString(newsAttachmentCursor.getColumnIndex(DatabaseHelper.NEWS_AT_NAME)); String fileUrl = newsAttachmentCursor.getString(newsAttachmentCursor.getColumnIndex(DatabaseHelper.NEWS_AT_URL)); String tempLowerUrl = fileUrl.toLowerCase(); if(tempLowerUrl != null && (tempLowerUrl.contains("png") || tempLowerUrl.contains("jpeg") || tempLowerUrl.contains("jpg") || tempLowerUrl.contains("ttif") || tempLowerUrl.contains("gif"))) { holder.newsAttachment.setVisibility(View.GONE); holder.newsImage.setVisibility(View.VISIBLE); Log.d("oopscv2", "File : "+fileUrl); new AQuery(mContext).id(holder.newsImage).image(newsAttachmentCursor.getString(newsAttachmentCursor.getColumnIndex(DatabaseHelper.NEWS_AT_URL)), true, true, 0, R.drawable.no_image, null, AQuery.FADE_IN); } else { holder.newsAttachment.setVisibility(View.VISIBLE); holder.newsImage.setVisibility(View.GONE); holder.newsAttachment.setText(fileName); } } } else { holder.newsAttachment.setVisibility(View.GONE); holder.newsImage.setVisibility(View.GONE); } } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { View v = inflater.inflate(R.layout.frag_news_row, parent, false); v.setTag(new ViewHolder(v)); return v; } private static class ViewHolder { TextView newsTitleText; TextView newsText; ImageView newsImage; TextView newsAttachment; public ViewHolder(View view) { // TODO Auto-generated constructor stub newsTitleText = (TextView) view.findViewById(R.id.newsTitleText); newsText = (TextView) view.findViewById(R.id.newsText); newsImage = (ImageView) view.findViewById(R.id.newsImage); newsAttachment = (TextView) view.findViewById(R.id.newsAttachment); } } } ``` Current Output: I want dynamic output like (temporary 4 attachment): I think dynamic view is useful for this but i dont know how to add dynamically view with formatting with onClick listener for all attachment. Hows its possible.? Updated Question after solved above question: Now i have following Updated Adapter: NewsNewAdapter.java ``` public class NewsAdapterNew extends SimpleCursorAdapter { DatabaseHelper dbHelper; LayoutInflater inflater; ViewHolder holder; ViewHolder.SubViewHolder subHolder; String DIRPATH = android.os.Environment.getExternalStorageDirectory() + File.separator + "TEMP" + File.separator; public NewsAdapterNew(Context context, int layout, Cursor c, String[] from, int[] to, int flags) { super(context, layout, c, from, to, flags); inflater = LayoutInflater.from(context); dbHelper = new DatabaseHelper(context); dbHelper.open(); } @Override public void bindView(View convertView, final Context context, Cursor cursor) { holder = (ViewHolder) convertView.getTag(); if(cursor.isNull(cursor.getColumnIndex(DatabaseHelper.NEWS_TITLE))) { holder.newsTitleText.setVisibility(View.GONE); } else { holder.newsTitleText.setVisibility(View.VISIBLE); holder.newsTitleText.setText(""+cursor.getString(cursor.getColumnIndex(DatabaseHelper.NEWS_TITLE))); } if(cursor.isNull(cursor.getColumnIndex(DatabaseHelper.NEWS_TEXT))) { holder.newsText.setVisibility(View.GONE); } else { holder.newsText.setVisibility(View.VISIBLE); String newsText = cursor.getString(cursor.getColumnIndex(DatabaseHelper.NEWS_TEXT)); newsText = Html.fromHtml(newsText).toString(); holder.newsText.setText(newsText); } /*************************** * Getting Child Cursor... */ Cursor newsAttachmentCursor; int newsId; /** * Setting up values of news_Attachment Table... */ newsId = cursor.getInt(cursor.getColumnIndex(DatabaseHelper.NEWS_SERVER_ID)); newsAttachmentCursor = dbHelper.getNewsAttachment(newsId); Log.d(TAG, "newsAttachmentCursor.getCount() : " +newsAttachmentCursor.getCount()); /** * Displaying news Attachment */ if(newsAttachmentCursor.getCount() > 0 && newsAttachmentCursor != null){ //newsAttachmentCursor.moveToFirst(); /** * Displaying NEWS_AT_NAME */ holder.layoutAttachment.removeAllViews(); newsAttachmentCursor.moveToFirst(); do { View viewAttachement = LayoutInflater.from(mContext).inflate(R.layout.attachment_layout, null); subHolder = new com.salesman.adapter.NewsAdapterNew.ViewHolder.SubViewHolder(viewAttachement); subHolder.newsImage.setTag(subHolder); subHolder.newsImageDownload.setTag(subHolder); subHolder.newsAttachmentFileName.setTag(subHolder); /** * Displaying If attachment has Images.... */ subHolder.fileName = newsAttachmentCursor.getString(newsAttachmentCursor.getColumnIndex(DatabaseHelper.NEWS_AT_NAME)); subHolder.fileUrl = newsAttachmentCursor.isNull(newsAttachmentCursor.getColumnIndex(DatabaseHelper.NEWS_AT_URL)) ? "" : newsAttachmentCursor.getString(newsAttachmentCursor.getColumnIndex(DatabaseHelper.NEWS_AT_URL)); subHolder.newsAttachmentFileName.setText(subHolder.fileName); String tempExt = subHolder.fileUrl.contains(".") ? subHolder.fileUrl.substring(subHolder.fileUrl.lastIndexOf(".")).toLowerCase() : ""; Log.d(TAG, "Temp Extension : "+tempExt); if(!tempExt.isEmpty()) { File myFile = new File(DIRPATH + subHolder.fileName); if(myFile.exists()) { subHolder.newsImageDownload.setVisibility(View.GONE); } else { subHolder.newsImageDownload.setVisibility(View.VISIBLE); } if(tempExt != null && tempExt.equals(".mp4") || (tempExt.equals(".jpeg") || tempExt.equals(".jpg") || tempExt.equals(".ttif") || tempExt.equals(".gif") || tempExt.equals(".png")|| tempExt.equals(".pdf")|| tempExt.equals(".docx")|| tempExt.equals(".doc")|| tempExt.equals(".xls")|| tempExt.equals(".xlsx")|| tempExt.equals(".ppt")|| tempExt.equals(".pptx")|| tempExt.equals(".txt")|| tempExt.equals(".zip"))) { subHolder.newsImage.setVisibility(View.VISIBLE); if(tempExt.equals(".pdf")) { new AQuery(mContext).id(subHolder.newsImage).image(R.drawable.ic_pdf); } else if(tempExt.equals(".doc") || tempExt.equals(".docx")) { new AQuery(mContext).id(subHolder.newsImage).image(R.drawable.ic_word); } else if(tempExt.equals(".xls") || tempExt.equals(".xlsx")) { new AQuery(mContext).id(subHolder.newsImage).image(R.drawable.ic_excel); } else if(tempExt.equals(".ppt") || tempExt.equals(".pptx")) { new AQuery(mContext).id(subHolder.newsImage).image(R.drawable.ic_ppt); } else if(tempExt.equals(".txt")) { new AQuery(mContext).id(subHolder.newsImage).image(R.drawable.ic_text); } else if(tempExt.equals(".zip")) { new AQuery(mContext).id(subHolder.newsImage).image(R.drawable.ic_zip); } else if(tempExt.equals(".mp4")) { new AQuery(mContext).id(subHolder.newsImage).image(R.drawable.ic_video); } else { subHolder.newsImage.setVisibility(View.VISIBLE); new AQuery(mContext).id(subHolder.newsImage).image(subHolder.fileUrl, true, true, 0, R.drawable.no_image, null, AQuery.FADE_IN); } } else { subHolder.newsImage.setVisibility(View.GONE); subHolder.newsImageDownload.setVisibility(View.GONE); } /*** * */ subHolder.newsImageDownload.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub com.salesman.adapter.NewsAdapterNew.ViewHolder.SubViewHolder tempHolder = ((com.salesman.adapter.NewsAdapterNew.ViewHolder.SubViewHolder)v.getTag()); //Toast.makeText(mContext, tempHolder.fileName.toString() + " is Downloading...", Toast.LENGTH_LONG).show(); if(InternetConnection.checkConnection(context)) { tempHolder.newsImageDownload.setVisibility(View.GONE); tempHolder.pBar.setVisibility(View.VISIBLE); new DownloadFileAsync().execute(tempHolder); } else { tempHolder.newsImageDownload.setVisibility(View.VISIBLE); tempHolder.pBar.setVisibility(View.GONE); AlertDialogManager.showAlertDialog(context, "Download failed", "The download was unable to complete. Please try again later.", false); } } }); subHolder.newsImage.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub try { com.salesman.adapter.NewsAdapterNew.ViewHolder.SubViewHolder tempHolder = ((com.salesman.adapter.NewsAdapterNew.ViewHolder.SubViewHolder)v.getTag()); Toast.makeText(mContext, "Downloaded : " + tempHolder.fileName.toString(), Toast.LENGTH_LONG).show(); File myFile = new File(DIRPATH + tempHolder.fileName.toString()); FileOpen.openFile(mContext, myFile); } catch (Exception e) { // TODO Auto-generated catch block Log.d(TAG, "Error While Opening : "+e.getLocalizedMessage()); } } }); /** Adding News Attachment Layout in Parent LinearLayout **/ holder.layoutAttachment.addView(viewAttachement); } viewAttachement.setTag(subHolder); } while(newsAttachmentCursor.moveToNext()); } else { holder.layoutAttachment.setVisibility(View.GONE); } } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { View v = inflater.inflate(R.layout.frag_news_row, parent, false); v.setTag(new ViewHolder(v)); return v; } private static class ViewHolder { TextView newsTitleText; TextView newsText; LinearLayout layoutAttachment; static class SubViewHolder { ImageView newsImage,newsImageDownload; TextView newsAttachmentFileName; ProgressBar pBar; String fileUrl; String fileName; public SubViewHolder(View subView) { // TODO Auto-generated constructor stub newsImage = (ImageView) subView.findViewById(R.id.newsImage); newsImageDownload =(ImageView) subView.findViewById(R.id.newsImageDownload); pBar = (ProgressBar) subView.findViewById(R.id.newsProgressBar); newsAttachmentFileName = (TextView) subView.findViewById(R.id.newsAttachment); } } public ViewHolder(View view) { // TODO Auto-generated constructor stub newsTitleText = (TextView) view.findViewById(R.id.newsTitleText); newsText = (TextView) view.findViewById(R.id.newsText); layoutAttachment = (LinearLayout) view.findViewById(R.id.linear_news_row_attachment); } } } ``` frag_new_row.xml ``` <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/newsLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="@drawable/bg_white_shadow" android:orientation="vertical" android:padding="10dp" > <TextView android:id="@+id/newsTitleText" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="3dp" android:text="News From" android:textColor="@android:color/black" android:textSize="@dimen/common_title_textview" android:textStyle="bold" /> <TextView android:id="@+id/newsText" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="News Text News Text" android:textColor="@android:color/black" android:textSize="@dimen/common_fontsize" /> <LinearLayout android:id="@+id/linear_news_row_attachment" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > </LinearLayout> </LinearLayout> ``` Problem: While scrolling sometimes all News Attachment per News going to blank. I think this problem occurring in adapter while binding view but i cant found. You will more understand this by following images. Output Before Scrolling: Output After Scrolling: Is my adapter code is wrong? What mistake i have done in Adapter? Your help would be appreciated. Thanks & Regards, Pratik