How create a button by programmatically for a GridLayout - android

I'm triying to create a GridLayout by programmatically in Kotlin. My code for the XML is this:
<androidx.constraintlayout.widget.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:background="#46FF4433"
tools:context=".MainActivity">
<androidx.gridlayout.widget.GridLayout
android:id="#+id/grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:rowCount="5">
app:columnCount="3"
</androidx.gridlayout.widget.GridLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
I want to set 15 buttons into my Grid. My mainActivity is this:
val gridLayout: GridLayout = findViewById(R.id.grid)
for (i in 1..10){
val button = Button(this)
button.text = "Boton: " + i
button.setBackgroundColor(Color.parseColor("#ffffff"));
gridLayout.addView(button)
}
But I need each button be like this:
<Button
android:id="#+id/button1"
app:layout_gravity="fill"
app:layout_columnWeight="1"
app:layout_rowWeight="1"
android:text="Button 1"
android:background="#ffffff"
/>
I think it has something to do with the layout param but I don't know how to set those atributes.

Take a look at GridLayout.LayoutParams and GridLayout.Spec. You can do something like the following:
val button = Button(this)
val lp = GridLayout.LayoutParams()
lp.setGravity(Gravity.FILL)
// GridLayout.spec is immutable, so one can be applied more than once.
// There are several other versions of GridLayout.spec which may be applicable.
lp.rowSpec = GridLayout.spec(row, 1.0f) // row start, weight
lp.columnSpec = GridLayout.spec(col, 1.0f) // column start, weight
button.layoutParams = lp
I haven't tested this, but it should get your started.

Related

Top-level Layout in Android XML is ALWAYS FrameLayout?

I was trying to set height of ConstraintLayout programmatically and I intended to use ConstraintLayout.LayoutParams. ConstraintLayout is a top-level layout in this XML. but I had weird experience when I set height from old to new with ConstraintLayout.LayoutParams and
ClassCastException occurred.
java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to androidx.constraintlayout.widget.ConstraintLayout$LayoutParams
the detail code is below.
Dialog
private fun initLayoutSize() = with(binding) {
dialog?.let {
val height = getDisplayHeight(it.window!!.windowManager)
val params = homeBottomSheetContainer.layoutParams as ConstraintLayout.LayoutParams // excpeiton here!!
params.height = (height * 0.3).toInt()
homeBottomSheetContainer.layoutParams = params
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:id="#+id/homeBottomSheetContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="#dimen/basic16"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<View
android:id="#+id/homeBottomSheetTopView"
android:layout_width="#dimen/basic30"
android:layout_height="#dimen/basic03"
android:layout_marginTop="#dimen/basic12"
android:background="#drawable/bottomsheet_top_radius_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/homeBottomLottoSearchNotice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/basic12"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:gravity="end"
android:padding="#dimen/basic04"
android:text="#string/ask_search"
android:textColor="#color/black"
android:textSize="#dimen/txt12"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/homeBottomSheetTopView"
tools:visibility="invisible" />
<EditText
android:id="#+id/homeLottoSearch"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="#string/input_lotto_round"
android:imeOptions="actionDone"
android:inputType="number"
android:maxLines="1"
android:textColor="#color/black"
android:textCursorDrawable="#drawable/shape_edittext_cursor_black"
android:textSize="#dimen/txt12"
android:visibility="invisible"
app:backgroundTint="#color/black"
app:layout_constraintBottom_toBottomOf="#id/homeBottomLottoSearchNotice"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#id/homeBottomLottoSearchNotice" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/homeBottomSheetLottoRV"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="#dimen/basic12"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/homeBottomLottoSearchNotice"
tools:listitem="#layout/item_lotto_all_round" />
</androidx.constraintlayout.widget.ConstraintLayout>
what happend?
I didn't use any FrameLayout in my XML and I couldn't find it anywhere. but why the android system tells me about FrameLayout? is FrameLayout a default top-level layout in Android View XML???
So, i changed the code with below one. and It worked!
private fun initLayoutSize() = with(binding) {
dialog?.let {
val height = getDisplayHeight(it.window!!.windowManager)
val params = homeBottomSheetContainer.layoutParams as FrameLayout.LayoutParams // change here!!
params.height = (height * 0.3).toInt()
homeBottomSheetContainer.layoutParams = params
}
}
But I'm so confused now. anyone help? and thank you in advance. :)
if you are setting only height then you may use more general ViewGroup.LayoutParams. all layout params are extending it, so there is no chance for class cast, no matter of parent
val params = homeBottomSheetContainer.layoutParams as ViewGroup.LayoutParams
besides that you may use is keyword for checking instance type

How to set text to TextView in LinearLayout in code?

I have this layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#color/white"
android:orientation="vertical">
<TextView
android:id="#+id/txt_daytime"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fontFamily="sans-serif-medium"
android:text="-"
android:textColor="#color/gray"
android:textSize="16sp" />
<TextView
android:id="#+id/txt_temp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fontFamily="sans-serif-medium"
android:text="-"
android:textColor="#color/black"
android:textSize="18sp" />
</LinearLayout>
I want to add it to my linear layout in main layout:
<LinearLayout
android:id="#+id/temp_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:orientation="horizontal">
in code. I'm using this:
val dayTime = listOf(DayTime.NIGHT, DayTime.MORNING, DayTime.DAY, DayTime.EVENING)
val tempContainer = binding.tempContainer
for (temp in dayTime) {
val weather = weatherData.getWeather(temp)
val view = LayoutInflater.from(requireContext()).inflate(R.layout.temp_layout, tempContainer) as LinearLayout
view.apply {
layoutParams = (layoutParams as LinearLayout.LayoutParams).apply {
weight = 1f
}
}
but how can i set values to those two TextViews in my reusing layout in code?
When i'm trying to get children in this view i can't choose TextView and also i can't set values to this children
((TextView) view.findViewById(R.id.txt_daytime)).setText("Custom1");
you can use this below code also
LayoutParams lparams = new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
TextView tv=new TextView(this);
tv.setLayoutParams(lparams);
tv.setText("test");
this.m_vwJokeLayout.addView(tv);
It's very simple to assign a value on text view.
1 ) you need to initialize textview like this:
val textView = findViewById(R.id.text_view_id) as TextView
2 ) set a text like this
textView.text = "Your text that you want to set"

Add buttons programmatically to Flow of ConstraintLayout?

I have seen the code for adding buttons to a ConstraintLayout in an existing question, but how do I do that with a Flow? That is, I do not want to define the top/left of the button relative to the ConstraintView itself, but I want the buttons to be next to the previous one and wrap at the end of the line.
I have tried the following but no button was showing.
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val flow = findViewById<Flow>(R.id.flow);
val lay = flow.parent as ConstraintLayout;
val cs = ConstraintSet();
cs.clone(lay);
for (i in 1 .. 10)
{
val btn = Button(this)
btn.text = "Test ${i}";
btn.id = 49393+i;
flow.addView(btn)
cs.constrainWidth(btn.id, 400);
cs.constrainHeight(btn.id, 100);
cs.applyTo(lay);
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ScrollView
android:id="#+id/sv"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textview1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/large_text"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
android:textIsSelectable="true" />
</ScrollView>
<androidx.constraintlayout.helper.widget.Flow
android:id="#+id/flow"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#FF0000"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
You haven't ever added the button to the layout. The Flow.addView method only adds it to the helper if it's already a child of the relevant ConstraintLayout.
From the documentation:
The referenced view need to be a child of the helper's parent.

Align programmatically elements in a ConstraintLayout

I create in Kotlin, a TextView, an EditText and a Button in a ConstraintLayout, and i would like to have them in center horizontally, and one below the others vertically, but whatever i tried they are still at top-left.
For now i have :
val layout = findViewById<ConstraintLayout>(R.id.mainLayout)
layout.removeAllViews()
//Here i try to set my alignments
var layoutParams = ConstraintLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
layoutParams.leftToLeft = ConstraintLayout.LayoutParams.MATCH_PARENT
layoutParams.rightToRight = ConstraintLayout.LayoutParams.MATCH_PARENT
layoutParams.topToTop = ConstraintLayout.LayoutParams.MATCH_PARENT
layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.MATCH_PARENT
layoutParams.verticalBias = 0.05f
val tv_dynamic = TextView(this)
tv_dynamic.text = "Text :"
tv_dynamic.layoutParams = layoutParams
layout?.addView(tv_dynamic)
layoutParams.verticalBias = 0.15f
val et_dynamic = EditText(this)
et_dynamic.setText("...")
et_dynamic.layoutParams = layoutParams
layout?.addView(et_dynamic)
layoutParams.verticalBias = 0.3f
val b_dynamic = Button(this)
b_dynamic.text = "Ok"
b_dynamic.setOnClickListener(View.OnClickListener(){ changenamevalidate(et_dynamic.text.toString())} )
b_dynamic.layoutParams = layoutParams
layout?.addView(b_dynamic)
I have based my settings on a xml TextView i already have :
<androidx.constraintlayout.widget.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:id="#+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="#layout/activity_main">
<TextView
android:id="#+id/TextViewTeam"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Team Name!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.05" />
</androidx.constraintlayout.widget.ConstraintLayout>
Add a android:layoutgravity="center_horizontal" attribute to your ConstraintLayout, like this:
<androidx.constraintlayout.widget.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:id="#+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="#layout/activity_main">
<TextView
android:id="#+id/TextViewTeam"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Team Name!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.05" />
</androidx.constraintlayout.widget.ConstraintLayout>

Add view to constraintLayout with constraints similar to another child

I have a constraint layout (alpha9) with views spread all over it, and I have one particular ImageView that I need to replicate and add more of like it.
The layout is like so :
The main purpose is to animate 5 of those "coin" imageViews when the button is pressed. The imageViews i need to generated sha'll have exact properties of the the imageView behind the Button down below (with same constraints)
What i tried to do is the following :
private ImageView generateCoin() {
ImageView coin = new ImageView(this);
constraintLayout.addView(coin,-1,originCoinImage.getLayoutParams());//originCoinImage is the imageView behind the button
coin.setImageResource(R.drawable.ic_coin);
coin.setScaleType(ImageView.ScaleType.FIT_XY);
coin.setVisibility(View.VISIBLE);
return coin;
}
And it failed. EDIT: It failed to show what i wanted , sometimes it shows a coin in the top left of the screen , sometimes it doesn't show anything but either way , the number of coins increments (meaning the animation is trying to actually do something and then calling the onAnimationFinished method)
I used for animation the library EasyAndroidAnimations
the code is as follows :
MainActivity.java
#OnClick(R.id.addCoin)
public void addCoin() {
// for (int x = 0 ; x < 5 ; x++){
final View newCoin = generateCoin();
sendCoin(newCoin, 300, new AnimationListener() {
#Override
public void onAnimationEnd(com.easyandroidanimations.library.Animation animation) {
incrementCoins();
constraintLayout.removeView(newCoin);
shakeCoin(targetCoinImage, 200, null);
}
});
// }
}
private void incrementCoins() {
coins++;
coinNumber.setText(String.valueOf(coins));
}
private void sendCoin(View coinView, long duration, AnimationListener listener) {
new TransferAnimation(coinView)
.setDestinationView(targetCoinImage)
.setDuration(duration)
.setInterpolator(new AccelerateDecelerateInterpolator())
.setListener(listener)
.animate();
}
private void shakeCoin(View coinView, long duration, AnimationListener listener) {
new ShakeAnimation(coinView)
.setDuration(duration)
.setShakeDistance(6f)
.setNumOfShakes(5)
.setListener(listener)
.animate();
}
activity_main.xml
<?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:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="seaskyways.canvasanddrawtest.MainActivity">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="Coins : "
android:textSize="30sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/coinNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="16dp"
android:layout_marginStart="8dp"
android:text="0"
android:textColor="#color/colorPrimary"
android:textSize="50sp"
android:textStyle="normal|bold"
app:layout_constraintBottom_toBottomOf="#+id/textView"
app:layout_constraintLeft_toRightOf="#+id/textView"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="#+id/textView" />
<ImageView
android:id="#+id/coinOrigin"
android:layout_width="50dp"
android:layout_height="50dp"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="#+id/addCoin"
app:layout_constraintLeft_toLeftOf="#+id/addCoin"
app:layout_constraintTop_toTopOf="#+id/addCoin"
app:srcCompat="#drawable/ic_coin"
app:layout_constraintRight_toRightOf="#+id/addCoin" />
<ImageView
android:id="#+id/coinTarget"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="#+id/coinNumber"
app:layout_constraintLeft_toRightOf="#+id/coinNumber"
app:layout_constraintTop_toTopOf="#+id/coinNumber"
app:srcCompat="#drawable/ic_coin" />
<Button
android:id="#+id/addCoin"
android:layout_width="0dp"
android:layout_height="75dp"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:text="Button"
android:textAlignment="center"
android:textSize="36sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
ConstraintLayout.LayoutParams cache its parameters, and is associated to the widget you use it on, so you cannot simply pass one widget's layoutParams to another.
You have to instead generate a new layoutParams for your new object, and copy the corresponding fields.
For example, if you have something like:
<?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:id="#+id/content_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/button"
android:layout_marginTop="16dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginStart="16dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginLeft="16dp" />
</android.support.constraint.ConstraintLayout>
Then you could do:
ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.content_main);
ConstraintLayout.LayoutParams params =
(ConstraintLayout.LayoutParams) button.getLayoutParams();
Button anotherButton = new Button(this);
ConstraintLayout.LayoutParams newParams = new ConstraintLayout.LayoutParams(
ConstraintLayout.LayoutParams.WRAP_CONTENT,
ConstraintLayout.LayoutParams.WRAP_CONTENT);
newParams.leftToLeft = params.leftToLeft;
newParams.topToTop = params.topToTop;
newParams.leftMargin = params.leftMargin;
newParams.topMargin = params.topMargin;
layout.addView(anotherButton, -1, newParams);
This would put the second button exactly in the same place as the one defined in XML.

Categories

Resources