How can I set the value for the attribute layout_weight for LinerLayout in android dynamically from Kotlin code ?
var orange : LinearLayout = findViewById(R.id.orangeLineFiveStars) as LinearLayout
Is it right code ? [It doesn't work in my app]
var orangeParams : LinearLayout.LayoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
orangeParams.weight = 0.33f
orange.layoutParams = orangeParams
This code doesn't work too
var orange.layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT,0.33f)
XML :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.sanke.ilafedoseev.raitmyworkstatistic.MainActivity">
<LinearLayout
android:layout_margin="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/orangeLineFiveStars"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="4dp"
android:background="#febe40"
android:orientation="horizontal"/>
<LinearLayout
android:id="#+id/whiteLineFiveStars"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
</LinearLayout>
</LinearLayout>
You need to remember that layout parameters are passed from child to parent view. You probably want to change layout_weight of some child of LinearLayout.
In your case you probably want to do something like this
(orangeLineFiveStars.layoutParams as LinearLayout.LayoutParams).weight = newOrangeWeight
(whiteLineFiveStars.layoutParams as LinearLayout.LayoutParams).weight = newWhiteWeight
It may be necessary to also request re-layout
parentLinearLayout.requestLayout()
You cant try something like this:
yourView.layoutParams.apply {
(this as LinearLayout.LayoutParams).weight = .33f //your value for weight
}.requestLayout()
Or
val param = yourView.cardView.layoutParams as LinearLayout.LayoutParams
param.weight = .33f
yourView.layoutParams = param
Related
I have a RecycleView in which I visualize some text. The text is entered through an EditText view in the bottom. The RecycleView contains a TextView which is has the text centered.
I have also a function that detects if the keyboard is visualised. When the keyboard is visualised, then some layout parameters are changed so that the EditText looks good. I also have a smooth scroll to the last position of the RecycleView.
When I reopen the keyboard again, the text is first drawn to the left of the screen. If I swipe, the text is re-aligned to center. That is very disturbing and I always want the text to be centered. I probably miss something when changing the parameters of the layouts.
KeyBoard openedListener:
// Function to see of keyboard is opened or not.
private void detectKeyBoard(){
final ConstraintLayout rootView = findViewById(R.id.activity_root);
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
float heightDiff = rootView.getRootView().getHeight() - rootView.getChildAt(0).getHeight();
if (!isRefSet){
refDiff = heightDiff;
isRefSet = true;
}
if (heightDiff > refDiff) {
LinearLayout.LayoutParams params = new
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
0);
params.weight = wRSmall;
mRecyclerView.setLayoutParams(params);
LinearLayout.LayoutParams eParams = new
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
0);
eParams.weight = wESmall;
mLinearInput.setLayoutParams(eParams);
if (mAdapter.getItemCount() > 0) {
mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount() - 1);
}
} else {
LinearLayout.LayoutParams params = new
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
0);
params.weight = wRStart;
mRecyclerView.setLayoutParams(params);
LinearLayout.LayoutParams eParams = new
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
0);
eParams.weight = wEStart;
mLinearInput.setLayoutParams(eParams);
if (mAdapter.getItemCount() > 0) {
mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount() - 1);
}
}
}
});
}
xml for RecycleView:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/activity_root"
tools:context="com.example.erikbylow.autoflash.TranslateActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/translate_linear"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.9"
android:scrollbars="vertical"
android:layout_gravity="center_horizontal"
android:id="#+id/translate_recycle"
android:background="#android:color/holo_blue_bright" />
<LinearLayout
android:layout_width="match_parent"
android:id="#+id/linear_input"
android:layout_height="0dp"
android:layout_weight="0.1"
android:orientation="horizontal">
<EditText
android:layout_width="0dp"
android:layout_weight="0.75"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:singleLine="true"
android:id="#+id/source_input"
android:hint="Type text to translate"/>
<Button
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="0.25"
android:layout_alignRight="#+id/source_input"
android:text="Translate"
android:clickable="true"
android:onClick="startTranslate"
android:background="#android:color/holo_green_dark"/>
</LinearLayout>
</LinearLayout>
TextView for Adapter:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:textSize="#dimen/active_text_size"
android:id="#+id/adapter_textview"/>
After swiping it is re-aligned:
EDIT: It did not work to remove android:layout_gravity="center_horizontal" in the recycle xml part.
Further, if the screen is full without the keyboard being opened, the text is moved to the right:
Can you comment the detectKeyBoard() function? Just to check if the same problem exists or not?
Just a guess -
I see that you are creating a new LayoutParams object and assign it to your mRecyclerView and mLinearInput.
As far as I know, this new LayoutParam object will replace what you have set in XML, including layout_gravity, layout_weight, etc.
Try getting existing LayoutParams from mRecyclerView and mLinearInput, and modify their values instead.
Cannot advise much because I do not really understand the reason behind resetting layout params in your case.
I am trying to change the layout width of two cardview element between MATCH_PARENT and 0dp. When I simulate the scenario via xml changes, it is correct, however, when I do it programmatically, it is not rendering as expected.
xml
<LinearLayout
android:id="#+id/lDates"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/card_margins"
android:layout_marginEnd="#dimen/card_margins"
android:layout_below="#id/lnrButtons"
android:orientation="horizontal">
<android.support.v7.widget.CardView
android:id="#+id/cardSectionA"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:cardElevation="0dp"
android:layout_marginEnd="#dimen/card_margins"
android:layout_marginBottom="#dimen/card_margins"
app:cardCornerRadius="4dp"
android:layout_weight="1">
<TextView
android:id="#+id/textLabelA"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/sample_value"/>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="#+id/cardSectionB"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:cardElevation="0dp"
android:layout_marginEnd="#dimen/card_margins"
android:layout_marginBottom="#dimen/card_margins"
app:cardCornerRadius="4dp"
android:layout_weight="1">
<TextView
android:id="#+id/textLabelB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/sample_value"/>
</android.support.v7.widget.CardView>
</LinearLayout>
java
//as-is scenario; cardSectionA and cardSectionB should be shown
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
cardSectionA.getLayoutParams().width,
LinearLayout.LayoutParams.WRAP_CONTENT
);
cardSectionA.setLayoutParams(params);
cardSectionB.setLayoutParams(params);
//should only show cardSectionA scenario
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
cardSectionA.setLayoutParams(params);
Thanks a lot.
Figured it out. To behave as expected, the margin and layout weight must also be set.
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
int margin = 10;
params.setMargins(margin, margin, margin, margin);
params.weight = 1;
cardSectionA.setLayoutParams(params);
I have a LinearLayout inside which I am including a different layout. Something like this
<LinearLayout
android:id="#+id/linear_layout"
android:layout_width="match_parent"
android:layout_height="20dp"
android:visibility="gone"
tools:visibility="visible">
<include
layout="#layout/new_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginBottom="4dp"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:layout_weight="1"/>
</LinearLayout>
Now what I would like to do is, to programmatically change the "marginBottom" of the included layout (new_layout). How can I do that?
I tried calling various LayoutParams and tried changing the margin, but not sure if it is the right approach. Any help greatly appreciated.
Thanks
Try this.. Make the Linear layout using your id
LinearLayout ll =(LinearLayout) findViewById(R.id.linear_layout);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, 20);
layoutParams.setMargins(left,top,right,bottom);
where you can pass the value in setMargins
and if you want to input value in dp.. Try this
public void setMargin(Context con,ViewGroup.LayoutParams params,int dp) {
final float scale = con.getResources().getDisplayMetrics().density;
// convert the DP into pixel
int pixel = (int)(dp * scale + 0.5f);
ViewGroup.MarginLayoutParams s =(ViewGroup.MarginLayoutParams)params;
s.setMargins(pixel,pixel,pixel,pixel);
yourView.setLayoutParams(params);
}
where you can pass your layout params
include.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:id="#+id/include_layout">
<ImageView android:layout_width="90dp"
android:layout_height="90dp"
android:src="#drawable/cross" />
</LinearLayout>
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">
<include layout="#layout/include"/>
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello"
android:padding="10dp" />
</LinearLayout>
MainActivity.class
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
LinearLayout included=(LinearLayout)findViewById(R.id.include_layout);
LinearLayout.LayoutParams params=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
params.setMargins(Math.round(10), Math.round(10), Math.round(10), Math.round(10));
//set margin...
included.setLayoutParams(params);
}
}
You should not directly change or modify margins in the <include> tag. This tag is just adding the layout resource in the current view hierarchy without adding an extra parent view container.
So essentially what you want to do is set margins on the root view container of the "included layout". That is you should directly call findViewById() for the root view and set all of your margins on it pro grammatically and as the included view's parent is a Linear-layout you should use
LinerLayout.LayoutParams params = (LinerLayout.LayoutParams) includedRootView.getLayoutParams();
params.setMargins();
includedViewRoot.setLayoutParams(params);`
You can change it by dimensions also
res/values/dimens.xml
res/values-small/dimens.xml
res/values-normal/dimens.xml
res/values-xlarge/dimens.xml
I think this code helpful...
include.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher" >
</ImageView>
</LinearLayout>
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include
android:id="#+id/include_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
layout="#layout/include" />
</LinearLayout>
MainActivity
package com.example.stackdemo;
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
public class MainActivity extends Activity {
LinearLayout include_layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
include_layout = (LinearLayout) findViewById(R.id.include_layout);
#SuppressWarnings("deprecation")
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
layoutParams.setMargins(0, 0, 0, 100);
include_layout.setLayoutParams(layoutParams);
}
}
I am creating a TextView dynamically. Here, I am creating a mainLayout in which I have two child layout and I wan gave them weight.
Here, is my Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:baselineAligned="false"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:orientation="horizontal">
<LinearLayout
android:id="#+id/Layout_second_overs"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="6"
android:orientation="vertical">
<!--Second textview overs-->
</LinearLayout>
<LinearLayout
android:id="#+id/Layout_second_balls"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:orientation="horizontal">
<!--Second textview balls--> //here i inflate 12 textview dynamically but not 12 seen on the device while i run the app.
</LinearLayout>
</LinearLayout>
</LinearLayout>
Code to create a 12 TextViews and put into layout.
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
for(int a = 0; a <= 12; a++)
{
TextView first = new TextView(getApplicationContext());
first.setLayoutParams(params);
first.setTextColor(Color.parseColor("#000000"));
first.setTextSize(12);
first.setGravity(Gravity.LEFT);
first.setPadding(5, 0, 5, 0);
first.setText("12");
layout_second_balls.addView(first); //This is my linear layout which id is Layout_second_balls
}
Problem is my all data are print into log but not visible on the device.
Please, help me to solve out this problem.
There are two issues
One is for the Layout Design related
Second based on the layout design and property you also need to
handle is while you are adding dynamically view into linear layout
Here what i have changed in Your xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:baselineAligned="false"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:orientation="horizontal">
<LinearLayout
android:id="#+id/Layout_second_overs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--Second textview overs-->
</LinearLayout>
<LinearLayout
android:id="#+id/Layout_second_balls"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1" android:background="#FF13C7FF"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
</LinearLayout>
In Layout_second_overs linearlayout height , Width & weight is the issue.
& in Layout_second_balls linear layout you have used weight as 1 so you also required layout_height as 0dp if orientation is horizontal
Now below things i have changed in code
LinearLayout.LayoutParams params = new
LinearLayout.LayoutParams
(0, LinearLayout.LayoutParams.WRAP_CONTENT);
for(int a = 0;a<=12;a++)
{
TextView first = new TextView(getActivity());
first.setLayoutParams(params);
first.setTextColor(Color.parseColor("#000000"));
first.setTextSize(12);
params.weight = 1; /// Need to give weight if you want equal size of textview inside Linear
first.setGravity(Gravity.LEFT);
first.setPadding(5, 0, 5, 0);
first.setText("12");
Layout_second_balls.addView(first); //This is my linear layout which id is Layout_second_balls
}
above things are based on the question which you ask
Suggestion
Avoid adding dynamic view like you asked . prefer to use ListView, GridView, RecyclerView for this type of functionality.
Your layout_second_overs requires all of your screen space - so your layout_second_balls is moved out of your screen.
If you want to see your two LinearLayouts beside each other, you need to set the layout_width to "0dp":
//pseudo, simply change width to 0dp
<LinearLayout
android:layout_height="40dp"
.... >
<LinearLayout
android:layout_width="0dp"
android:layout_weight="6"/>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"/>
</LinearLayout>
To replace this kind of loops you are supposed to use a RecyclerView. It is easy to use and responsive (since your list will be scrollable).
The things you have to remember while implementing a RecyclerView are to add an adapter and a LayoutManager to it.
For your example :
LayoutManager manager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, true);
YourAdapter adapter = new YourAdapter([...]);
RecyclerView recyclerView = findViewById(R.id.your_recyclerview_here);
recyclerView.setLayoutManager(manager);
recyclerView.setAdapter(adapter);
If you need any advices for creating your adapter just ask.
You can use this line of code.
LinearLayout layout_second_balls=(LinearLayout) findViewById(R.id.Layout_second_balls);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
for(int a = 0;a<=12;a++)
{
TextView first = new TextView(getApplicationContext());
first.setLayoutParams(params);
first.setTextColor(Color.parseColor("#000000"));
first.setTextSize(12);
first.setGravity(Gravity.LEFT);
first.setPadding(5, 0, 5, 0);
first.setText("12");
layout_second_balls.addView(first);
}
i run this code in my emulator and i got this out put.
You have to assign index for a view while performing addview(view,index) set index for each textview created in for loop like layout_second_balls.addView(first,index);
Code should look like :
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
for(int a = 0; a <= 12; a++)
{
TextView first = new TextView(getApplicationContext());
first.setLayoutParams(params);
first.setTextColor(Color.parseColor("#000000"));
first.setTextSize(12);
first.setGravity(Gravity.LEFT);
first.setPadding(5, 0, 5, 0);
first.setText("12");
layout_second_balls.addView(first,a);
}
Hope it will work.
On all layouts I have a header and footer in common, how do I change the in between layout at runtime?
main_latout.xml-
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include
android:id="#+id/header"
layout="#layout/mytask_header"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:layout_alignParentTop="true"/>
<include
android:id="#+id/footer"
layout="#layout/mytask_footer_ads"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"/>
<RelativeLayout
android:id="#+id/common_place_for_xml"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#id/header"
android:layout_above="#id/footer"
android:background="#android:color/darker_gray">
</RelativeLayout>
</RelativeLayout>
I want to change other layout in the RelativeLayout with id common_place_for_xml ?
I am newbie? Please help.
You can add views to your relative layout in run time. Here's a sample:
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.common_place_for_xml);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
Button dummy = new Button(this);
dummy.setText("Hello");
dummy.setLayoutParams(params);
relativeLayout.addView(dummy);
Not sure if I understand what you want, but I'll try to help.
Try giving your outer RelativeLayout an id, such as "parentLayout", and another XML file with the name newLayout which will be replacing your "common_place_for_xml" layout.
Then at runtime try:
RelativeLayout parentLayout = findViewById(R.id.parentLayout);
RelativeLayout childLayout = parentLayout.findViewById(R.id.common_place_for_xml);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) childLayout.getLayoutParams();
int index = parentLayout.indexOfChild(childLayout);
parentLayout.removeView(childLayout);
RelativeLayout newLayout = findViewById(R.id.newLayout);
parentLayout.addView(newLayout, index);
newLayout.setLayoutParams(params);