I've got a simple function that takes a JSONObject and, extracting the relevant data from the object, creates a new view, adding it to an existing linear layout. The code is as follows:
private void createFriendFilter(JSONObject j) {
final int size = 40;
try{
String name = j.getString("DISPLAY_NAME");
String fPic = j.getString("PROFILE_PIC");
BitmapDrawable bmd = ImageUtil.decode(fPic, size);
LayoutInflater i = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
CheckedTextView c = (CheckedTextView)i.inflate(R.layout.friend, null);
c.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 50));
c.setText(name);
c.setCompoundDrawables(bmd, null, null, null);
c.setCompoundDrawablePadding(10);
friendsContainer.addView(c);
Log.i(TAG, "Friend Filter Created..."+name);
}catch (Exception e) {
Log.i(TAG, "Error Creating Friend Filter...");
}
}
I call this function from a for-loop, iterating through each JSONObject in a JSONArray. Basically what it does is creates a "friend filter" for each friend in the array. This is the problem: The new view is successfully added to the Linear Layout (friendsContainer) for the first friend, but fails to add any other friends to the Linear Layout. However, I know that the new view is supposed to have been added even when its not showing up because my Log indicates that the filter has been successfully created for that friend. To summarize, this function adds the first friend to the layout, but I cannot see any others. Any thoughts would be much appreciated. Thanks!
Maybe you have the friendsContainer LinearLayoutset to orientation horizontal (horizontal is the default value for orientation) and your TextView have width set to fill_parent, so your first TextView fills the hole width of the LinearLayout and pushes the other TextView out of the screen.
Did you check the hierarchy viewer to be sure it's not a layout problem?
(Sorry can't comment on your post, so I had to answer)
Related
I followed the below link to dynamically add a layout multiple times using inflater and AddView()
Is there a way to programmatically create copies of a layout in android?
I used a loop to create multiple entries. But only one entry is comming up which is the result of last loop index
Below is my C# code
I can see only one child inside the parent which is the result of last loop.
What I missed?
var parent = FindViewById<RelativeLayout>(Resource.Id.ParentLayoutWrapper);
for (int i = 0; i < 4; i++)
{
var view = LayoutInflater.Inflate(Resource.Layout.RepeatingLayout, parent, false);
var txtView = view.FindViewById<TextView>(Resource.Id.textViewSample);
txtView.Text = i.ToString()+ " Android application is debugging";
txtView.Id = i;
parent.AddView(view, i);
}
The original post you worked from had a LinearLayout as the parent layout, not a RelativeLayout like you have. When you add a view (or another layout) to a LinearLayout, it gets positioned below (when LinearLayout has vertical orientation) any existing elements in the layout. However, the elements in a RelativeLayout need to use positioning properties to determine where they will be in the RelativeLayout, so every time you add the new layout, RepeatingLayout, since you are not changing the layout options, the view/layout is added over the existing view/layout. So change the parent layout to a LinearLayout in your layout file and then this should work:
LinearLayout parent = FindViewById<LinearLayout>(Resource.Id.parentLayout);
for (int i = 0; i < 4; i++)
{
var view = LayoutInflater.Inflate(Resource.Layout.RepeatingLayout, null);
var tv = view.FindViewById<TextView>(Resource.Id.textViewSample);
tv.Text = i.ToString() + " Android application is debugging";
parent.AddView(view);
}
Trying to do the same with a RelativeLayout as the parent layout highly complicates things unnecessarily.
Code :
LinearLayout linearLayout2;
final JSONArray answer=jsonObject1.getJSONArray("answer");
//Here get Answer from question
((ViewGroup) findViewById(R.id.linearLayout2)).removeView(linearLayout2); //Here remove preselected radiobuttons
linearLayout2 = new LinearLayout(TestActivity2.this); //Here create new viewgroup when user click next and previous
linearLayout2.setOrientation(LinearLayout.HORIZONTAL);
linearLayout2.setGravity(Gravity.FILL_HORIZONTAL);
indexAns=new String[answer.length()];
for(int j=0;j<answer.length();j++)
{
final JSONObject jsonObject2 = answer.getJSONObject(j);
final String answer_ans=jsonObject2.getString("answer_ans"); //get answer from loop
answer_id=jsonObject2.getString("answer_id");
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
//Here create radio buttons depending on answer loop
final TextView textBtn = new TextView(TestActivity2.this);
textBtn.setId(Integer.parseInt(answer_id));
textBtn.setLayoutParams(params);
textBtn.setAllCaps(true);
textBtn.setTextSize(12);
textBtn.setPadding(5,5,5,5);
textBtn.setGravity(Gravity.LEFT | Gravity.CENTER |Gravity.RIGHT);
textBtn.setTextColor(Color.parseColor("#000000"));
indexAns[j]=answer_id;
You may want to post your layout xml files. Looks like you are manipulating the layout programatically, which, in most cases in unnecessary. You can accomplish the same goal via xml layout files.
Also, you can save a lot of time using styles for formatting.
Check out the following layout documentation
https://developer.android.com/guide/topics/ui/declaring-layout.html
Check out the TextView documentation:
https://developer.android.com/reference/android/widget/TextView.html
I am adding views dynamically to a relative layout (let's say container) in a for loop. There is some thing strange I am noticing. When adding rows one below the other in a relative layout in a for loop, I see that the first time a few of the views are overlapping. But when I lock and unlock the screen, I can see that the views are placed correctly.
Should I be aware of something when adding views dynamically to a relative layout?
Edit
I have found a solution as to how to get rid of this (please check my answer). But I would be more than glad to accept an answer that analyses this problem and tells me why this happens.
I have simplified to code and the comments should give a good idea as to what I am doing.
int prev_id=ID_OF_THE_ELEMENT_ABOVE;
/*Empty RelativeView with width and height as MATCH_PARENT and WRAP_CONTENT respectively*/
RelativeLayout container=(RelativeLayout) findViewById(R.id.container);
while(ThereIsData){
/*GET THE DATA HERE THAT HAS TO BE ASSIGNED TO EACH TEXTVIEW*/
...
/* ADD TEXTVIEW #1 below prev_id/
...
...
/*ADD TEXTVIEW #2 (WITH BASELINE OF TEXTVIEW#
...
...
/*TEXTVIEW #3 (BELOW TEXTVIEW#1)*/
...
...
/*TEXTVIEW #4 (BELOW TEXTVIEW#2)*/
...
...
/*ASSIGN THE ID OF TEXTVIEW#3 TO prev_id SO THAT
IN THE NEXT ITERATION TEXTVIEW#1 CAN USE prev_id
*/
prev_id=ID(TEXTVIEW#2);
/*ADD TEXTVIEWS CREATED IN THIS ITERATION*/
container.addView(TEXTVIEW#1);
container.addView(TEXTVIEW#2);
container.addView(TEXTVIEW#3);
container.addView(TEXTVIEW#4);
}
It is due to the fact that you are having a RelativeLayout with height as WRAP_CONTENT, and adding a view doesn't refresh the whole container at that time.. so as you answered you can add a line to measure the dimensions explicitly or invalidate the view to recreate it completely.
In any case LinearLayout would be better to opt-for as it will automatically arrange the children in horizontal or vertical manner and you can even add the new view in any place other than last position and it will automatically be updated..
I used to struggle against common issues a year ago, when I was working on a library for dynamically creating layouts from XML files (as Android does not support this). So when you dynamically add views to a RelativeLayout you have to take in mind a few things:
Create the container View (in this case the RelativeLayout)
Create all views without assigning any layout parameters.
Add all child views to the container.
Iterate over the container's children and populate each child's layout parameters. This is needed because when the relational constraints are applied an Excpetion is thrown if the relative View is missing (was not previously added to the container).
This is an example code taken from the project I used to work on. Take in mind that it is just a single part so it contains references to classes that are not defined in the Android API. I am sure it will give you the basic idea of dynamically creating RelativeLayot:
private void setChildren(RelativeLayout layout, T widget,
InflaterContext inflaterContext, Context context,
Factory<Widget, View> factory) {
List<Widget> children = widget.getChildren();
if (Utils.isEmpty(children))) {
return;
}
// 1. create all children
for (Widget child : children) {
View view = factory.create(inflaterContext, context, child);
layout.addView(view);
}
// 2. Set layout parameters. This is done all children are created
// because there are relations between children.
for (Widget child : children) {
try {
View view = ViewIdManager.getInstance().findViewByName(layout, child.getId());
if (view != null) {
populateLayoutParmas(child, view);
}
} catch (IndexNotFoundException e) {
Log.e(LOG_TAG, "Cannot find a related view for " + child.getId(), e);
}
}
}
I have not yet found the answer to why this is happening. But I have found a solution. After adding each row in the loop, call container.measure(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
This seems to solve the problem. But I really think that container.addView() should also be calling measure().
/*ADD TEXTVIEWS CREATED IN THIS ITERATION*/
container.addView(TEXTVIEW#1);
container.addView(TEXTVIEW#2);
container.addView(TEXTVIEW#3);
container.addView(TEXTVIEW#4);
//---------------------------------------------------------------------
container.measure(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
//Declare globally
LinearLayout[] layout;
ImageView[] imageView1;
ImageView[] imageView2;
ImageView[] imageView3;
// Initialize your layout. It would be RelativeLayout too. Just reference to it.
LinearLayout ll = (LinearLayout) findViewById(R.id.mylinear);
// set listview row size as your demand
layout = new LinearLayout[200];
imageView1 = new ImageView[200];
imageView2 = new ImageView[200];
imageView3 = new ImageView[200];
for (int i = 0; i < 200; i++) {
layout[i] = new LinearLayout(this);
layout[i].setBackgroundResource(R.drawable.book_shelf);
// layout[i].setLayoutParams(new
// LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.FILL_PARENT,
// 120));
layout[i].setLayoutParams(new LinearLayout.LayoutParams(
android.widget.LinearLayout.LayoutParams.FILL_PARENT, 220));
imageView1[i] = new ImageView(this);
imageView2[i] = new ImageView(this);
imageView3[i] = new ImageView(this);
imageView1[i].setLayoutParams(new LinearLayout.LayoutParams(0, 200,
0.33f));
imageView1[i].setPadding(0, 20, 0, 0);
imageView1[i].setImageResource(R.drawable.bibid_one_bankim);
imageView2[i].setLayoutParams(new LinearLayout.LayoutParams(0, 200,
0.33f));
imageView2[i].setPadding(0, 20, 0, 0);
imageView2[i].setImageResource(R.drawable.bibid_two_bankim);
imageView3[i].setLayoutParams(new LinearLayout.LayoutParams(0, 200,
0.33f));
imageView3[i].setImageResource(R.drawable.dena_pawna);
imageView3[i].setPadding(0, 20, 0, 0);
layout[i].setId(i);
layout[i].setClickable(true);
final int j = i;
layout[i].addView(imageView1[i]);
layout[i].addView(imageView2[i]);
layout[i].addView(imageView3[i]);
ll.addView(layout[i]);
}
}
Try adding your views in vertical Linear Layout.
Following link might help you
http://www.myandroidsolutions.com/2012/06/19/android-layoutinflater-turorial/
Inflate your layout in for loop.
I'm trying to create a menu list from json data in a LinearLayout using the follwing code:
LinearLayout myLayout = (LinearLayout)findViewById(R.id.info);
for (int i = 0; i < jsonArray.length(); i++) {
try {
jsonObj = jsonArray.getJSONObject(i).getJSONObject("store");
textView = new TextView(context);
textView.setText(jsonObj.getString("name"));
textView.setId(jsonObj.getInt("id"));
myLayout.addView(textView);
} catch (JSONException e) {
e.printStackTrace();
}
}
It works, but only until the third record, after that all the text views are not shown.
I think there may be a limit or something that doesn't allow me to add more textviews.
Any idea?
I think first you should make your layout linear and vertical. Do its orientation vertical in the xml.
android:orientation
You're better of using a ListView and ArrayAdapter, as far as I know addView is no longer supported, and throws an exception when used in recent versions of Android.
This is a great tutorial on the subject.
I actually trying something quite straightforward, however android and java are making my life not easy. The idea is to scroll to a specified child in the table layout.
I am using a Layoutinflater to add the entries to the table layout like the following :
TableLayout tl = (TableLayout)findViewById(R.id.myTableLayout3);
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.element_news, null);
TextView firstname = (TextView) itemView.findViewById(R.id.tvname);
firstname.setText(FN + " " + iLN);
TextView date = (TextView) itemView.findViewById(R.id.tvdate);
date.setText(newPD);
TextView post = (TextView) itemView.findViewById(R.id.tvpost);
post.setText(c.getString(iP));
post.setFocusable(true);
tl.addView(itemView, new TableLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
I tried to use the getChildAt() for the tablelayout and I do get the child, however when I use the child it returns for everything "0".
Example Code:
LinearLayout row = (LinearLayout) tl.getChildAt(1);
TextView tv = (TextView) row.getChildAt(1);
tv.requestFocus();
Log.w("news", Integer.toString(tv.getHeight()));
For the TextView Height it returns "0" eventhough it contains multiple lines and the requestfocus() does not work either.
So how can I scroll to the child in the table layout?
Thanks in advance for any help.
That code sample doesn't work because you probably use it in the onCreate method and at that time the UI isn't drawn yet so the views don't have any dimensions. If this is the case you could simply post a Runnable on one of your views to delay a bit the dimensions gathering until after the onCreate method like this:
// post the Runnable
tl.post(new Runnable() {
#Override
public void run() {
LinearLayout row = (LinearLayout) tl.getChildAt(1);
// get the top position relative to the parent
int top = tr.getTop();
// scroll to that top position the wrapping ScrollView
sv.scrollTo(0, top);
}
});
There is something strange about your code(from my point of view), if the code above doesn't work you should post more details about your layout files and use scenario.