Android - Set FrameLayout width dynamically - android

I've got a FrameLayout which I want to grow as time continues.
I've implemented a Runnable-Interface.
public void run() {
time_value++;
FrameLayout fl_dateTime = (FrameLayout)findViewById(R.id.game_DateTime);
LayoutParams lp_fl_dateTime = fl_dateTime.getLayoutParams();
lp_fl_dateTime.width = time_value;
handler.postDelayed(this, 100);
}
Why doesn't this work? O_O

You need to set the layout params back after modifying them.
View#setLayoutParams(ViewGroup.LayoutParams lp)

I was able to do this by setting the initial size of the frame to 0dp and then just setting the minWidth to whatever I wanted.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:background="#android:color/black"
android:id="#id/layout"
android:minHeight="50dp"
android:measureAllChildren="false">
item.setMinimumWidth(10dp);

Related

Programmatically setting height of LinearLayout inside ScrollView not working

I have a ScrollView whose unique child is a LinearLayout:
<ScrollView
android:id="#+id/d_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:id="#+id/d_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/transparency"
android:orientation="vertical"/>
</ScrollView>
I later dynamically add children to the LinearLayout by using a LayoutInflator (let's say 5 children in this example), and they all have a weight of 1 (so equal heights). I want to only have 4.5 children visible at a time. To do this, I have used a post method to do change the layout_height property of the LinearLayout once the height of the ScrollView is known:
if (n > visibleItems) { // here n = 5 and visibleItems = 4.5
dScroll.setFillViewport(false);
dScroll.post(() -> {
int height = dScroll.getHeight();
ViewGroup.LayoutParams lp = dLayout.getLayoutParams();
lp.height = (int) Math.round(n * height / visibleItems);
dLayout.setLayoutParams(lp);
});
}
However, when I do this, the LinearLayout and its children behave as if their height was set to wrap_content (which is not the case). When using the Layout Inspector in Android Studio, I find that the layout_height of the LinearLayout is set to 1071 (the correct computed value), but the getHeight() method returns 578.
I have tried several combinations of requestLayout(), invalidate() and forceLayout() but it didn't change anything.
Keeping the fillViewport property of the ScrollView to true makes the LinearLayout take the height of the ScrollView, so in this case 964px instead of the 1071 that I want.
Edit: the problem really comes from LinearLayout. If I add a RelativeLayout between the ScrollView and LinearLayout like so:
<ScrollView
android:id="#+id/d_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<RelativeLayout
android:id="#+id/d_rel"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/d_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/transparency"
android:orientation="vertical"/>
</RelativeLayout>
</ScrollView>
and apply the new height to the RelativeLayout instead:
if (n > visibleItems) { // here n = 5 and visibleItems = 4.5
dScroll.setFillViewport(false);
dScroll.post(() -> {
int height = dScroll.getHeight();
ViewGroup.LayoutParams lp = dRel.getLayoutParams();
lp.height = (int) Math.round(n * height / visibleItems);
dRel.setLayoutParams(lp);
});
}
then the RelativeLayout takes the correct height (1071px), but the LinearLayout within it (that is in match_parent height) is still only 578px high.

The content of a LinearLayout isn't visible

I tried to add some GUI elements like an ImageView or a TextView to a LinearLayout programmatically. But the elements aren't displayed.
To see if a element is drawn or not, I set a different background color for each element. The result was that I can only see the background color of the LinearLayout. But why?
public class MyLinearLayout extends LinearLayout {
public MyLinearLayout(Context context) {
super(context);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
setLayoutParams(params);
setBackgroundColor(Color.RED);
imageView = new ImageView(context);
params = new LinearLayout.LayoutParams(100, 100);
imageView.setLayoutParams(params);
imageView.setBackgroundColor(Color.BLUE);
addView(imageView);
}
}
The strange thing is that I can see the red background color of the LinearLayout but in the size of the ImageView. If I add some other GUI elements like a TextView, I can see how the LinearLayout grows. But I can not see the TextView.
I'm really confused, because this not the first time I do something like this. Can u tell me what I'm doing wrong?
This is a snippet of the layout.xml file:
<LinearLayout android:layout_width="match_parent"
android:layout_height="45dp"
android:id="#+id/bottom_bar"
android:layout_alignParentBottom="true"
android:gravity="bottom">
<FrameLayout android:id="#+id/block_edit_delete_layout"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:background="#drawable/block_edit_delete_selector">
<ImageView android:layout_height="match_parent"
android:layout_width="wrap_content"
android:src="#drawable/block_edit_delete"
android:scaleType="fitXY"
android:contentDescription="#string/delete"/>
</FrameLayout>
<LinearLayout
android:id="#+id/block_edit_progress"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="horizontal"/>
<FrameLayout android:id="#+id/block_edit_random_layout"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:background="#drawable/block_edit_delete_selector">
<ImageView android:layout_height="match_parent"
android:layout_width="wrap_content"
android:src="#drawable/block_edit_random"
android:scaleType="fitXY"
android:contentDescription="#string/random_numbers"/>
</FrameLayout>
</LinearLayout>
The LinearLayout with the ID block_edit_progress is the container layout of multiple instances of the class MyLinearLayout. The instances are added in the code:
for(int i = 0; i < numberOfMyLinearLayouts; i++) {
MyLinearLayout v = new MyLinearLayout(getContext());
addView(v);
}
I hope this helps.
If i convert your code to xml, it would be something like:
<LinearLayout layout_width=wrap_content, layout_height = wrap_content>
<LinearLayout id= MyLinearLayout>//just an idea, syntax may be wrong
<LinearLayout layout_width= 100, layout_width=100>
<ImageView color=BLUE>
</ImageView>
</LinearLayout>
</LinearLayout>
</LinearLayout>
Whenever you call setLayoutParams on a View, parameter params you give should be parent element.
Try something like if you want linearlayout to be the parent of your linearlayout, use MATCH_PARENT for width, height if you want your view to span the width, height of view's parent
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
setLayoutParams(lp);//lp is parent view
Also try this, just in case views are getting added to right of your views, and you are not able to see them on screen
yourview.setOrientation(LinearLayout.VERTICAL);
Change the width and height of linear layout to match_parent and see how it changes. wrap_content will only show the content of the linear layout, which seems to be your problem.
I solved the problem. (Or found a workaround)
I moved the complete initialization stuff out of the constructor of the MyLinearLayout. If I then adding a View after the layout has been completely generated, everything works.
Like this:
MyLinearLayout ll = new MyLinearLayout(getContext());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(100, 100);
ll.setLayoutParams(params);
ll.setBackgroundColor(Color.RED);
ImageView v = new ImageView(getContext());
params = new LinearLayout.LayoutParams(50, 50);
v.setLayoutParams(params);
v.setBackgroundColor(Color.GREEN);
ll.addView(v);
addView(ll);
I don't know why the other way doesn't work. Thanks for the fast answers!

what is root layout in XML?

<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

Dynamically setting relative dimension of a linearlayout

I want to resize my LinearLayout (or a view) to a dimension which is relative to the parent or itself. For example, I want the width to be 1/3 of the parent's width. Or, the height should be same as its own width. I don't want to use any constants , so that it works for all devices.
adding code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<LinearLayout android:id="#+id/ll_board"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
...
</LinearLayout>
code:
public class GMActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
LinearLayout board_layout = (LinearLayout)findViewById(R.id.ll_board);
// I wanted to resize board_layout here ..
// getParent().getWidth() returns 0
Log.d("gm", "layout: " + ((LinearLayout) board_layout.getParent()).getWidth());
// ..
}
}
getWidth() is giving 0. Is it too early to call this? If yes, what is the correct place to call this?
Basically my intention is to make the width of the layout a fraction of the screen size width, and, height same as its own width.
Considering layout your LinearLayout and that its parent it's another LinearLayout:
Get the parent's width:
int parentWidth = ((LinearLayout) layout.getParent()).getWidth();
Get the view's width:
int viewWidth = ((LinearLayout) layout).getWidth();
set the
view.setHeight(viewWidth );
view.setWidth(parentWidth / 3);
I found height=width solution (square shaped layout) in LinearLayout in Square Form

How do I calculate the required height of a GridView that is inside of a ScrollView on Android?

I have a GridView inside of a LinearLayout inside of a ScrollView that pages in data from the server. Beneath the GridView is a button to load more data. My GridView will have an ultimate height that is larger than the screen. If I set the height of my GridView to either wrap_content or parent_fill, it sizes itself to the exact available on-screen height and does not scroll at all, cropping out the extra rows. If I explicitly set the layout_height to something large, like 1000dip, scrolling behaves properly, however I cannot predict the final height of my scroll view apriori.
How do I programmatically determine the necessary height of a GridView to get the desired behaviour?
Here is my layout below. As you can see I set the height to 1000dip, but that is bogus, I need that value to get set automatically/programmatically:
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:layout_weight="1"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/grid"
android:layout_width="fill_parent"
android:layout_height="1000dip"
android:columnWidth="70dp"
android:numColumns="auto_fit"
android:verticalSpacing="0dp"
android:horizontalSpacing="0dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:background="#000000"
android:layout_weight="1"
/>
<Button
android:id="#+id/load_more"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Load More Foo"
/>
</LinearLayout>
</ScrollView>
Here is one way to do this, if someone needs it. A bit of a hack but does the trick. You have to set GridView initially big enough for all the views (e.g. 10000dip)
final GridView imageContainer = // your GridView
imageContainer.getViewTreeObserver().addOnGlobalLayoutListener( new OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
imageContainer.getViewTreeObserver().removeGlobalOnLayoutListener( this );
View lastChild = imageContainer.getChildAt( imageContainer.getChildCount() - 1 );
imageContainer.setLayoutParams( new LinearLayout.LayoutParams( LayoutParams.FILL_PARENT, lastChild.getBottom() ) );
}
});
I know it's an old case, but I had a similar problem where my ScrollView contained multiple LinearLayouts, which in their turn contained a header and a GridView.
Basically I made categorised sections with headers containing images belonging to that category.
The GridView had to have a flexible height.
I found a lot of answers about overriding onMeasure(), but it worked only on some devices, not all. The height would eventually be 1, or 3 or just 0, displaying only a few pixels of the image.
StretchingGridView class
I overrode the drawableStateChanged() method with this code, inspired by #Karitsa's solution:
#Override
public void drawableStateChanged() {
getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
getViewTreeObserver().removeOnGlobalLayoutListener( this );
View lastChild = getChildAt( getChildCount() - 1 );
if (lastChild != null) {
int height = Math.max(lastChild.getBottom(), getColumnWidth());
float child = getAdapter().getCount();
float col = getNumColumns();
int rows = (int) Math.ceil(child / col);
height = rows * getColumnWidth() + (getHorizontalSpacing() * rows-1);
setLayoutParams( new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, height ) );
}
}
});
}
Note: My GridView uses square images, so I base the height on their width. I don't think it works well with flexible grid item heights.
Apparently GridViews inside ScrollViews are not kosher in Android-land. Switching to ListView with custom-made rows. That seems to behave better.

Categories

Resources