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.
Related
I have a layout for recyclerview adapter that it's like a instagram. That means it has a slider for images and like button and etc.
Now I want to load multiple images in the slider and clients should change images with dragging like instagram exactly.
First I used PosterSlider library, but its problem is that doesn't have scale type so I cannot manage images size.
So now I wanna try ViewFLipper, but my problem is I don't know how can I use ViewFlipper like a slider.
That means how can I change images by dragging in ViewFLipper?
If you have another idea for changing picture, I will be glad to hear it.
This is my code for ViewFlipper that I know it is wrong, because it shows just one Image and it doesn't have any code for changing picture by dragging:
try {
JSONArray jsonArray = new JSONArray(newsLetterList.get(position).Jsonsrc);
for(int i = 0;i < jsonArray.length(); i++){
setImageInFlipper(jsonArray.getString(i),holder);
}
} catch (JSONException e) {
e.printStackTrace();
}
setImageInFLipper method:
private void setImageInFlipper(String imgUrl,NewsLetterViewHolder holder){
ImageView imageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
Glide.with(context).load(imgUrl).into(imageView);
holder.slider.addView(imageView);
}
You can take some reference from here. They have implemented the same viewflipper slide both with next(flip) button and without using any button. Hope that helps!
I am struggling at one thing. Let's say I have linear layout with set height and width is match_parent. I will have a set number of views 1 to 6 and I don't know at runtime how much I will receive from server. The problem is, how can I sort them in a layout so they scale their width accordingly to number of views present ? If there are more than 3 views I need to put them in two lines.
I was thinking about using layout weight, but can't think about solution that can put them to two lines. Any ideas ?
You have to dynamically add views to linear layout.
First create container layout in xml.
<LinearLayout
android:id="#+id/containerLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
Then check,
if(list.size()<=3)
{
Then assign weight to container. i.e weight=list.size
for(int i=0;i<size;i++)
{
TextView textview = new TextView(this);
textview.setText(brandName);
textview.setWeight(1f);
container.addView(textview);
}
}
else
{
int totalRows= (list.size/3)+(list.size%3);
int count=0;
for(int i=0;i<totalRows;i++)
{
LinearLayout newLL = new LinearLayout(mContext);
newLL.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
newLL.setOrientation(LinearLayout.HORIZONTAL);
for(int j=count;j<count+3;j++)
{
count++;
TextView textview = new TextView(this);
textview.setText(brandName);
newLL.addView(textview);
}
container.addView(newLL);
}
}
You have to do something like this.This is not actual code.
You should use listview in your rooted LinearLayout and design single list item in an other xml layout , create a custom adapter for your single list item and set the adapter to your list view . this answer will help you how to create custome adapter
In my Project , I have 80 TextViews.
I should set their text from 1 to 80 once project runs , and they dont need to be changed in future.
Except TxtViews , I have some other things in my Layout, the TextViews are under ImagesViews. actually I have 80 imagesViews and under them are 80 TextViews. I want to set text of textViews from 1 to 80 dynamically.
I know I can do it in my layout.xml ,
but its really time consuming.
is there any way to do that by code?
for example with a for cycle or something like that?
Create a ViewGroup suitable for your needs in the layout, for example:
<LinearLayout
android:id="#+id/linear_layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
Then you create you TextView instances programatically, and add them to the LinearLayout, like this:
LinearLayout layout = (LinearLayout)findViewById(R.id.linear_layout);
for(int i = 0; i < 80; i++) {
TextView textView = new TextView(getContext());
textView.setText("text" + i);
layout.addView(textView);
}
Optionally, you can add tags or whatever to locate them again. Alternatively just iterate over the layouts subviews.
If you know that 80 Textview fixed then you should take listview for that.
Listview Benefit
Memory management automatically
Listview manage indexing
If they share the same layout, except for the text, and could be displayed as a list, you could use an ArrayAdapter and pass the values from code.
http://www.mkyong.com/android/android-listview-example/
Checkout the below example,
public class MainActivity extends Activity {
LinearLayout linearLayout ;
ScrollView scrollView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = (HorizontalScrollView) findViewById(R.id.scrollViewActivityMain);
}
private void populateTextViews() {
linearLayout = new LinearLayout(this);
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
//add all textViews here
for(int i=0; i < 80; i++){
TextView myTextView = new TextView(this);
myTextView.setText("My TextView "+i);
myTextView.setGravity(Gravity.CENTER);
linearLayout.addView(myTextView);
}
scrollView.addView(linearLayout);
}
}
Don't forget to put that scrollView in your xml.
Let me know if it works for you...
If your TextViews are declared on the xml, wrap them on another view so you can reference it on the java code later, then simply use a for.
Something like:
View view = findViewById(R.id.your_wrapper);
for(int i=0; i<((ViewGroup)view).getChildCount(); i++) {
View nChild = ((ViewGroup)view).getChildAt(i);
TextView tv = (TextView) nChild;
tv.setText(String.valueOf(i + 1));
}
If not, you can simply create them dynamically inside your java code, and append them to a layout like LinearLayout.
Example:
xml
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/linear"
/>
Java code
LinearLayout ll = (LinearLayout) findViewById(R.id.linear);
for (int i = 1; i <= 80; i++) {
TextView tv = new TextView(this); // Assuming you're inside an Activity.
int count = ll.getChildCount();
tv.setText(String.valueOf(i));
ll.addView(tv, count, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
}
EDIT: But truly, you should use RecyclerView or ListView for that if your values are not going to change.
You can read more about RecyclerView here, and on ListView here.
Second edit: From what you're saying on your comments, you REALLY should be using ListView instead of your current design. The solutions above and from the other answers won't work at all for your problem.
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'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)