I have the following LinearLayout in which I'm dynamically inserting views:
<LinearLayout
android:id="#+id/loyaltycardlist"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:background="#00f"
android:orientation="vertical"/>
and the Java code:
LinearLayout loyaltyCardLL = (LinearLayout)findViewById(R.id.loyaltycardinfo);
for(MyCard thisCardNode : mLoyaltyCards)
{
LinearLayout item = (LinearLayout)getLayoutInflater().inflate(
R.layout.activity_view_node_details_loyaltycard, null);
item.setTag(thisCardNode);
TextView tv = (TextView)item.findViewById(R.id.loyaltycard_item_title);
tv.setText(thisCardNode.getTitle());
... etc
loyaltyCardLL.addView(item);
}
loyaltyCardLL.invalidate();
The containing linear layout never expands to hold the layouts I've added, even though I'm calling invalidate().
And tips on why this is happening?
Related
I am working on an Android project and I have an issue with the layout.
What I have is a JSONArray that I loop round inflating a new TableRow and within the loop round another array within the JSON array to populate it with fields. The fields are populated by inflating an XML file and adding this view to the table row. However, at the moment nothing shows up in the row.
Below is my TableRow XML file:
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"/>
Below is my TextView XML:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="#color/black"
android:padding="5dp"/>
Below is how I am populating the TableRow and the TextView:
for (int i = 0; i < result.length(); i++) {
final TableRow tr = (TableRow) getLayoutInflater(getArguments()).inflate(R.layout.result_table_row_light_theme, resultTable, false);
if (i == 0) {
tr.setBackgroundColor(getResources().getColor(R.color.appPrimaryColour));
} else if (i % 2 == 0) {
if (settings.getInt(Defines.SharedPreferenceSettings.APPLICATION_THEME,
com.BoardiesITSolutions.Library.R.style.LibAppTheme) == com.BoardiesITSolutions.Library.R.style.LibAppTheme) {
tr.setBackgroundColor(getResources().getColor(R.color.resultRowLightThemeAlternateRow));
}
}
JSONArray array = result.getJSONArray(i);
for (int j = 0; j < array.length(); j++) {
final TextView textView;
textView = (TextView) getLayoutInflater(getArguments()).inflate(R.layout.result_textview, tr, false);
textView.setText(array.getString(j));
if (i == 0) {
textView.setTypeface(null, Typeface.BOLD);
textView.setGravity(Gravity.CENTER_HORIZONTAL);
}
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
tr.addView(textView);
}
});
}
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
resultTable.addView(tr);
}
});
}
If I change my TextView XML file so that the layout_width is wrap_parent instead of 0dp then everything is shown on the screen.
However, when the textview is 0dp and the layout_weight is 1 then nothing is displayed, however I would have expected each text view to be evenly distributed across the width of the screen to fill the space.
What I should probably mention, don't know if it makes a difference, is the TableView is within a HorizontalScrollView. The row should fit in the width of the screen, if the data is smaller than the screen, but if the row won't fit, then the view will be horizontally scrollable.
UPDATE 1
Below is the XML that hosts the TableLayout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="horizontal">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TableLayout android:id="#+id/resultTable"
android:stretchColumns="*"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</TableLayout>
</HorizontalScrollView>
</LinearLayout>
</ScrollView>
</RelativeLayout>
What I should probably mention, don't know if it makes a difference, is the TableView is within a HorizontalScrollView.
It is a logical error to tell a child view inside a scrolling container to match_parent or fill the available space in any way. A scrolling container, like ScrollView or HorizontalScrollView measures its one-and-only child view as UNSPECIFIED so that the child can grow beyond the parent bound in that one direction (and, thus, be scrollable).
The child of a scrolling container is not given what the "available space" would be for it to fill, and operations like layout weight have no effect if the parent's dimension is not well-defined.
The row should fit in the width of the screen, if the data is smaller than the screen, but if the row won't fit, then the view will be horizontally scrollable.
The functionality you are looking for is fillViewport (docs link), which tells the scrolling container to force the child to match it's size if the measured width (in the horizontal case) is less than the parent. Use this in place of applying a weight.
Try this :
public void createTextView(Context context, LinearLayout parent) {
final TextView v = new TextView(context);
parent.addView(v); // Mandatory!
v.post(new Runnable() { // In UI Thread. View Must be added to parent before getting layout params!
#Override
public void run() {
// Get params:
LinearLayout.LayoutParams lParams = (LinearLayout.LayoutParams) v.getLayoutParams();
// Set only target params:
lParams.width = 0;
lParams.weight = 1;
v.setLayoutParams(lParams);
}
});
}
Can you try to do your layout in XML (just to debug it, with dummy data)? Does it work as expected?
The docs mention that:
children of a TableRow do not need to specify the layout_width and layout_height attributes in the XML file. TableRow always enforces those values to be respectively MATCH_PARENT and WRAP_CONTENT.
Not sure if that means that it'll also mess stuff up if you try to set these values. As you've found, it's clearly not just ignoring them if they are set.
The other part says that the parent of the TableRow should be a TableLayout - is that the type of resultTable (you mentioned TableView) - otherwise it will behave as a LinearLayout with horizontal orientation.
I am having a LinearLayout whose visibility is directly affected by the click of a TextView. This LinearLayout has more TextViews dynamically added inside. My LinearLayout viewQuickLinks starts out with a visibility of gone. In my oncreate I call addQuickLinks which then adds several TextViews to the LinearLayout. None of these TextViews have a set visibility. I click on the TextView to change the LinearLayout to visible and space is added, but there are no TextViews.
My xml file (just to add a note this is all in a scrollview):
<TextView
android:id="#+id/textQuickLinksTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableRight="#drawable/navigation_expand"
android:text="#string/quick_links_title"
android:textSize="25sp"
android:visibility="visible" />
<LinearLayout
android:id="#+id/viewQuickLinks"
android:layout_width="fill_parent"
android:layout_height="1dip"
android:visibility="gone"
android:orientation="vertical" />
Changing the LinearLayout to visible and gone:
private void setUpQuickLinks() {
final TextView quickLinksTitleText = (TextView) findViewById(R.id.textQuickLinksTitle);
quickLinksTitleText.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
LinearLayout viewQuickLinks = (LinearLayout) findViewById(R.id.viewQuickLinks);
if (viewQuickLinks.getVisibility() == View.VISIBLE){
viewQuickLinks.setVisibility(View.GONE);
quickLinksTitleText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.navigation_expand, 0);
}
else{
viewQuickLinks.setVisibility(View.VISIBLE);
quickLinksTitleText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.navigation_collapse, 0);
}
}
});
quickLinksClickListeners();
}
Why are the TextViews not appearing when the LinearLayout is Visible?
Thank you for any help!
Try changing android:layout_height to fill_parent. Why is it 1 dip?
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rootLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ScrollView
android:id="#+id/scrollView1"
android:layout_width="wrap_content"
android:layout_height="80dp"
android:scrollbars="none"
android:layout_x="0dp"
android:layout_y="0dp"
android:fillViewport="true" >
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="0dp"
android:layout_y="0dp"
android:src="#drawable/background" />
</LinearLayout>
</ScrollView>
</LinearLayout>
this is my xml file .which is pity much simple. My intention is to increase height of scroll view dynamically and the image (which is with the scroll view) view will be shown gradually.so how can i do that and What is rootLayout here and How i call rootLayout from my code ??
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
runOnUiThread(new Runnable()
{
public void run() {
secondCounter++;
yourNewHeight += 10;
sv.getLayoutParams().height = yourNewHeight;
LinearLayout root = (LinearLayout) findViewById(R.id.rootLayout);
root.invalidate();
Log.v("", "" +sv.getLayoutParams().height);
if(secondCounter == 20){
timer.cancel();
}
}
});
}
}, delay, period);
this is my code in java file.But its not working . guys can you help me out..!!!
The root of this layout is the AbsoluteLayout.
You can obtain a reference to this root View together with all of its children in your Activity using a call like:
mRootView = ((ViewGroup)findViewById(R.id.rootLayout));
Note that AbsoluteLaoyut is long depreciated and you will probably want to replace it with an alternative ViewGroup, such as a LinearLayout, RelativeLayout, etc. depending on the rest of your layout and how you want to do things.
If you've inflated your XML appropriately in code (ie called setContentView()) you should be able to reference rootLayout using:
AbsoluteLayout root = (AbsoluteLayout) findViewById(R.id.rootLayout);
Though if you're just trying to increase the height of the ScrollView, it makes more sense to directly call:
ScrollView scroll = (ScrollView) findViewById(R.id.scrollView1);
And as above, you should probably use a RelativeLayout or LinearLayout rather than an AbsoluteLayout.
Since ScrollView can only have one Child within it, you can use ScrollView itself as your root element with a LinearLayout as a direct and only child to it, inside which u can add any views you want.
And AbsoluteLayout is deprecated, and I'd recommend not to use it
I have a LinearLayout view element inside a ScrollView (main.xml):
<ScrollView ...>
<LinearLayout
android:id="#+id/root"
android:orientation="vertical"
>
<TextView .../>
<EditText .../>
...
</LinearLayout>
</ScrollView>
As you see above, there are also some other elements inside the root LinearLayout .
Now, I would like to programmatically(dynamically) add more views to the LinearLayout (id="root").
I tried the following way to add more child views to this root:
Firstly, I created my child view which is in a separate layout file:
child.xml
<LinearLayout
android:id="#+id/child"
>
<TextView id="mytxt"... />
<ListView id="mylist".../>
</LinearLayout>
Secondly, I inflate & get two instances of above child view, initialize elements inside:
/***inflate 1st child, initialize its elements***/
LinearLayout child_1 = (LinearLayout) inflater.inflate(R.layout.child, null);
TextView txt1 = (TextView)child_1.findViewById(R.id.mytxt);
txt1.setText("CAR");
ListView list1 = (ListView)child_1.findViewById(R.id.mylist);
// Code to initialize 'list1' (I did not paste code here)
/*** inflate 2nd child, initialize its elements ****/
LinearLayout child_2 = (LinearLayout) inflater.inflate(R.layout.child, null);
TextView txt2 = (TextView)child_2.findViewById(R.id.mytxt);
txt2.setText("PLANE");
ListView list2 = (ListView)child_2.findViewById(R.id.mylist);
// Code to initialize 'list2' (I did not paste code here)
Finally, I add them to root LinearLayout:
//get root
View contentView = inflater.inflate(R.layout.main, null);
LinearLayout root = (LinearLayout) contentView.findViewById(R.id.root);
//add child views
root.add(child_1);
root.add(child_2);
When I run my app on device, I can only see child_2 layout without seeing child_1 under 'root', why??
in LinearLayout default orientation is horizontal set it vertical.......
from
http://developer.android.com/reference/android/widget/LinearLayout.html
see
The default orientation is horizontal.
and you set text in txt1.setText("PLANE"); set in txt2.setText("PLANE");
both text set in same textview.....
txt1.setText("CAR");
txt1.setText("PLANE");
How do you create your layout? Do you do it through setContentView(int)? Then you should retrieve that instance by doing this in your activity:
findViewById(R.id.root);
I have 2 layout xml files: "highlights.xml" and "highlights_cell.xml".
Here is a simplified version of each. I've removed the width/height/etc and just kept the important attributes...
highlights.xml
<LinearLayout>
<uk.co.jasonfry.android.tools.ui.SwipeView android:id="#+id/swipe_view" />
<uk.co.jasonfry.android.tools.ui.PageControl android:id="#+id/page_control" />
</LinearLayout>
highlights_cell.xml
<LinearLayout android:orientation="vertical">
<LinearLayout android:id="#+id/linear_layout1" android:orientation="horizontal">
<ImageView android:id="#+id/logo" />
<LinearLayout android:id="#+id/linear_layout2" android:orientation="vertical">
<TextView android:id="#+id/title" />
<TextView android:id="#+id/subtitle" />
</LinearLayout>
</LinearLayout>
<ScrollView android:id="#+id/scroll_view">
<TextView android:id="#+id/description" />
</ScrollView>
</LinearLayout>
The idea is that I want to add several "highlights_cell" to "highlights" through a loop.
I've thrown together some test code as follows but, as it's not working, I suspect that I'm not adding the cell layouts correctly, or perhaps I shouldn't be using "inflater"...
/** Declare shared variables */
SwipeView mSwipeView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState){
//Initialise layout and variables
super.onCreate(savedInstanceState);
setContentView(R.layout.highlights);
//Setup controls
mSwipeView = (SwipeView) findViewById(R.id.swipe_view);
LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
//Loop through collection and add views
for(int i=0; i<7;i++)
{
//Create the itemView to use layout xml for each cell
View itemView = inflater.inflate(R.layout.highlights_cell, null);
//Set values within cell
TextView title = (TextView) itemView.findViewById(R.id.title);
title.setText("HELLO WORLD_" + i);
//add the itemView to main view
mSwipeView.addView(itemView);
}
}
Is this the correct way to add layouts dynamically to a parent layout?
Thanks!
It looks good except for a few things.
Because you are adding views to your custom ViewGroup, you will have to be sure that it correctly lays out and displays its children.
Also, when you add a View to a ViewGroup, you specify the LayoutParams that views can have in that ViewGroup.
Some more info about creating a custom ViewGroup
http://about-android.blogspot.com/2010/05/create-dynamic-view-group.html
custom ViewGroup example?