I am up to something a little different from the standard custom listviews. I am having an activity which is responsible for displaying data retrieved from Parse.com database. The data contents are mostly in html format and may have any amount of text and images.
What I have already done:
- Retrieving the data from the database.
- Putting the data in a linear layout which is dynamically created according to the contents of the html.
What I wan to achieve:
- Add the layout to a listview as a row layout.
I have gone through a number of forums but I am still unable to find a solution using which I can inflate a listview without an xml layout and can assign my dynamic layout instead.
The activity source code:
public class MainActivity extends ActionBarActivity {
ArrayList<String> originalContentList = new ArrayList<String>();
ArrayList<String> reversedList = new ArrayList<String>();
ImageView imageView1;
Bitmap bitmap;
RelativeLayout parent_layout;
ParseObject user;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
parent_layout = (RelativeLayout) findViewById(R.id.parent_layout);
login("xxx@xxx.com", "xxx");
// reverseArraylist();
}
private void loopThroughArrayAndAttach(){
LinearLayout llInner = new LinearLayout(this);
llInner.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
parent_layout.addView(llInner);
for (int i = 0; i < originalContentList.size(); i++) {
if (hasNoImagess(originalContentList.get(i)) == true) {
// No images.
TextView myText = geneterTextView(originalContentList.get(i));
llInner.addView(myText);
} else {
ImageView myImage = geneterImageView(originalContentList.get(i));
llInner.addView(myImage);
}
}
}
public static boolean hasNoImagess(String contents){
Document doc = Jsoup.parse(contents);
Element element = doc.body();
Elements elements = element.select("img");
if (elements.isEmpty()) {
return true;
} else {
return false;
}
}
public ImageView geneterImageView(String imgContent){
// Will need to run via background thread - like aysnc
// Extract the image file via jsoup
// Insert it into a imagevieww
// Inser that into a layout.
Log.d("IN IMAGE ", " " + imgContent);
Document doc = Jsoup.parse(imgContent);
Elements img = doc.getElementsByTag("img");
Bitmap returnedBitmap = null;
ImageView iv = new ImageView(this);
for (Element el : img) {
String src = el.absUrl("src");
System.out.println("src attribute is : " + src);
// new DownloadImageTask((ImageView)
// findViewById(R.id.imageView1)).execute(src);
try {
//returnedBitmap = new LoadImage().execute(src).get();
WorkerThread mWorkerThread = new WorkerThread(iv);
mWorkerThread.execute(src);
// imageView1.setImageBitmap(returnedBitmap);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// ImageView iv = new ImageView(this);
iv.setImageBitmap(returnedBitmap);
return iv;
}
public TextView geneterTextView(String textContent){
// Will need to run via background thread.
Log.i("In TEXT ", " " + textContent);
TextView tv = new TextView(this);
tv.setText(Html.fromHtml(textContent));
return tv;
}
private class WorkerThread extends AsyncTask<String, String, Bitmap> {
private WeakReference<ImageView> imageViewReference;
public WorkerThread(ImageView imageView) {
super();
imageViewReference = new WeakReference<ImageView>(imageView);
}
@Override
protected Bitmap doInBackground(String... args) {
// bitmap = null;
try {
bitmap = BitmapFactory.decodeStream((InputStream) new URL(args[0]).getContent());
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if (result != null && imageViewReference.get() != null) {
imageViewReference.get().setImageBitmap(result);
}
}
}
// to login to parse
private void login(final String username, String password){
ParseUser.logInInBackground(username, password, new LogInCallback() {
@Override
public void done(ParseUser user, ParseException e){
if (e == null) {
// if login sucess
// Start intent
// loginSuccess();
Toast.makeText(MainActivity.this, "Success", Toast.LENGTH_SHORT).show();
CloudCallStudentPosts(user);
} else {
Toast.makeText(MainActivity.this, "Failure", Toast.LENGTH_SHORT).show();
}
}
});
}
// //to get data from parse
public void CloudCallStudentPosts(ParseObject s){
setRichStory(s);
}
private void setRichStory(ParseObject s){
// Simialr to setStory, once implemented delete setStory()
new AddStoryAsync(s).execute();
}
class AddStoryAsync extends AsyncTask<Void, Object, Void> {
private static final String TAG = "LazyListView";
ParseObject s;
public AddStoryAsync(ParseObject s) {
this.s = s;
Log.w("In richStory", "ParseObject Id: " + s.getObjectId());
}
@Override
protected void onPreExecute(){
}
@Override
protected Void doInBackground(Void... unused){
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("userid", this.s.getObjectId());
params.put("skip", 0);
ParseCloud.callFunctionInBackground("studentsPosts", params, new FunctionCallback<List<List<ParseObject>>>() {
@Override
public void done(List<List<ParseObject>> postList, com.parse.ParseException arg1){
if (postList == null) {
} else {
if (postList.size() > 0) {
// CustomWebView cwb;
for (int i = 0; i < postList.size(); i++) {
// final Post post = new Post();
if (postList.get(i).get(0).get("htmlContent") == null) {
if (postList.get(i).get(0).getNumber("type") != null) {
// post.setType(postList.get(i).get(0).getNumber("type"));
}
if (postList.get(i).get(0).getString("question") != null) {
// post.setQuestion(postList.get(i).get(0).getString("question"));
}
if (postList.get(i).get(0).getString("textContent") != null) {
// post.setQuestion(postList.get(i).get(0).getString("textContent"));
}
if (postList.get(i).get(0).getString("answer") != null) {
// post.setAnswer(postList.get(i).get(0).getString("answer"));
}
if (postList.get(i).get(0).getCreatedAt() != null) {
// post.setCreatedAt(postList.get(i).get(0).getCreatedAt());
}
// Need to re-get map and trip and photo
// types
if (postList.get(i).get(0).getParseFile("photo") != null)
postList.get(i).get(0).getParseFile("photo").getDataInBackground(new GetDataCallback() {
@Override
public void done(byte[] imageByte, ParseException arg1){
if (arg1 == null) {
Bitmap bmp = BitmapFactory.decodeByteArray(imageByte, 0, imageByte.length);
if (bmp == null) {
}
}
}
});
if (postList.get(i).get(0).getJSONArray("tripPoints") != null) {
// post.setTripPoints(postList.get(i).get(0).getJSONArray("tripPoints"));
}
if (postList.get(i).get(0).getParseGeoPoint("location") != null) {
// post.setLocation(postList.get(i).get(0).getParseGeoPoint("location"));
}
// publishProgress(post);
}
if (postList.get(i).get(0).get("htmlContent") != null) {
Log.e("htmlContent parse", postList.get(i).get(0).get("htmlContent").toString());
// Parse HTML String using JSoup library
String HTMLSTring = postList.get(i).get(0).get("htmlContent").toString();
Document html = Jsoup.parse(HTMLSTring);
Elements paragraphs = html.getElementsByTag("p");
for (org.jsoup.nodes.Element paragraph : paragraphs) {
String paragraphText = paragraph.toString();
Log.e("paragraphText", paragraphText);
originalContentList.add(paragraphText);
}
loopThroughArrayAndAttach();
}
// publishProgress(post);
// This is where we publish
}
}
}
}
});
return (null);
}
@Override
protected void onProgressUpdate(Object... object){
Log.w("onProgressUpdate ", " " + object[0].getClass());
Log.w("adding to arrayPostList ", " " + object[0].getClass());
}
@Override
protected void onPostExecute(Void unused){
}
}
}
The method loopThroughArrayAndAttach()
is generating the linearlayout
programmatically and adding imageviews and textviews to it dynamically. For now the linearlayout
is attached to the parent layout which, which needs to be substituted with a listview.
The layout:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scrollView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/parent_layout">
</RelativeLayout>
</ScrollView>
How to achieve the desired output?