I have a LinearLayout(horizontal) inside a ScrollView. I'm trying to add TextView's and Button's inside LinearLayout with programmatically.
My code works without errors but with little glitch. My ScrollView only stretch for TextView not for Button's. Sorry for the inadequate explanation, maybe screenshot helps: Imgur.
❒ Eve gir. is a Button the rest is TextView.
How can I make ScrollView stretch and wrap my Button's too. i tried set the fillViewPort but it did not work.
TextView adding code:
private fun createText(prTx: String, color: String) {
val text = TextView(this)
text.text = prTx
text.gravity = Gravity.CENTER_HORIZONTAL
text.textSize = 18F
text.setShadowLayer(5F,3F,2F,Color.BLACK)
when (color) {
"n" -> text.setTextColor(Color.WHITE)
"p" -> text.setTextColor(Color.rgb(255,182,193))
"m" -> text.setTextColor(Color.rgb(182,207,255))
"cm" -> text.setTextColor(Color.rgb(182, 242, 227))
"olay" -> {
text.setShadowLayer(5F,3F,2F,Color.rgb(100,0,166))
text.setTextColor(Color.rgb(75,0,130))
}
}
text.textAlignment = TextView.TEXT_ALIGNMENT_CENTER
text.layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT)
val layout = findViewById<LinearLayout>(R.id.llText)
layout.addView(text)
}
Button adding code
private fun createButton(prTx: String, clk: Int) {
val button = Button(this)
button.text = prTx
button.setBackgroundColor(Color.TRANSPARENT)
button.gravity = Gravity.CENTER_HORIZONTAL;
button.textSize = 18F
button.transformationMethod = null;
button.setTextColor(Color.WHITE)
button.setShadowLayer(10F,5F,5F, Color.BLACK)
button.textAlignment = TextView.TEXT_ALIGNMENT_CENTER
button.setOnClickListener {
when (clk) {
}
}
button.layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT)
val layout = findViewById<LinearLayout>(R.id.llText)
layout.addView(button)
}
Layout's XML codes
<ScrollView
android:id="#+id/sv"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:background="#5B34515E"
android:fadeScrollbars="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#+id/ivMutfak"
app:layout_constraintHeight_default="wrap"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="#+id/clMiddle"
app:layout_constraintTop_toBottomOf="#+id/clMiddle"
app:layout_constraintVertical_bias="0.0">
<LinearLayout
android:id="#+id/llText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:orientation="vertical" />
</ScrollView>
The problem was not ScrollView, it was LinearLayout. Problem solved when I deleted it android:layout_margin's of `LinearLayout. I still don't know why but this solution worked for me.
You should use LinearLayout.LayoutParams.WRAP_CONTENT instead of ViewGroup.LayoutParams.MATCH_PARENT. Try this code
LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
Related
Looking for a way to align an Imageview which would be in line with the textview and have it be able to adjust if the textview is too long and will extend to the next line. The reason it is an imageView, is I want it to be clickable
I haven't been successful, I have tried image and text spans and also constraintlayout but I can't seem to the get following result below:
Thanks
[1]: https://i.stack.imgur.com/onPT9.png
Here is a way to add an image to the end of the text in a TextView whether the text spans one or several lines. The approach is to add a space to the end of each text string and replace that space with an ImageSpan overlaid with a ClickableSpan.
Here is the layout used:
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="#android:color/holo_blue_light"
android:padding="8dp"
android:text="#string/test_string_1"
android:textSize="28sp" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="#android:color/holo_blue_light"
android:padding="8dp"
android:text="#string/test_string_2"
android:textSize="28sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
And the string resources:
<string name="test_string_1"><b>This</b> is a short string.</string>
<string name="test_string_2"><b>This</b> is some text that spans several lines and is just used as an example.</string>
After waiting for the layout to complete, we can add the images to the end of the text for each TextView.
binding.root.doOnNextLayout {
// Make the drawables truly clickable.
binding.textView1.text = addEndImage(binding.textView1)
binding.textView1.movementMethod = LinkMovementMethod.getInstance()
binding.textView2.text = addEndImage(binding.textView2)
binding.textView2.movementMethod = LinkMovementMethod.getInstance()
}
private fun addEndImage(textView: TextView): Spannable {
// Get out (probable) StaticLayout from the TextView and some of its attributes.
val size = textView.layout.run {
val lastLine = lineCount - 1
-getLineAscent(lastLine) * 2 / 3
}
// Get the text and add a space for the spans at the end. If we are certain that the
// text can be accurately represented by an unspanned String, we could just use
// "${binding.textView.text} ".toSpannable()
val text = SpannableStringBuilder(textView.text).append(" ")
// Get the drawable and size it to fit on our last line.
val d = AppCompatResources.getDrawable(requireContext(), R.drawable.circle)!!
d.setBounds(0, 0, size, size)
// Set the ImageSpan to replace the space we added at the end. Vertical positioning
// and the size of the image may need to be tweaked.
val span = ImageSpan(d, ImageSpan.ALIGN_BASELINE)
text.setSpan(span, text.length - 1, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
// Set the ClickableSpan to overlay the ImageSpan we added at the end.
val clickableSpan = MyClickableSpan()
text.setSpan(
clickableSpan,
text.length - 1,
text.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
return text
}
class MyClickableSpan : ClickableSpan() {
override fun onClick(widget: View) {
Toast.makeText(widget.context, "Clicked", Toast.LENGTH_SHORT).show()
}
}
If you need to use an ImageView for accessibility or other reasons, you can do that as follows.
The layout:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/holo_blue_light"
android:padding="8dp"
android:text="#string/test_string_2"
android:textSize="28sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/imageView"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="8dp"
android:src="#drawable/circle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Again, after layout is complete, we can do the following that will give the ImageView top and left margins that will place it at the end of the text.
binding.root.doOnNextLayout {
val imageView = binding.imageView
imageView.setOnClickListener() {
Toast.makeText(requireContext(), "Clicked", Toast.LENGTH_SHORT).show()
}
val textView = binding.textView2
val layout = textView.layout
val imageY = textView.bottom
val shiftX = layout.getLineRight(layout.lineCount - 1)
val shiftY =
-(imageView.y - imageY) - imageView.paddingTop - textView.height + layout.getLineBaseline(
layout.lineCount - 1
) - imageView.height / 2
val lp = (imageView.layoutParams as ViewGroup.MarginLayoutParams)
lp.marginStart = shiftX.toInt()
lp.topMargin = shiftY.toInt()
imageView.layoutParams = lp
}
You will have to work with the exact size and placement, but this is a technique that will work.
I'm android studio noob. I'm trying to fill a grid layout from kotlin activity.
My code for the xml is this:
<androidx.gridlayout.widget.GridLayout
android:id="#+id/grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:rowCount="3"
app:columnCount="2">
</androidx.gridlayout.widget.GridLayout>
In the MainActivity there is a for to create every buttom like this:
val gridLayout: GridLayout = findViewById(R.id.grid)
for (i in 1..10){
val button = Button(this)
button.text = "Boton: " + i
// GridLayout.add(Buttom)
}
Who can I do it?
Thank you
Modify Your Function as Per the given Code.
for (i in 1..10){
val button = Button(this)
button.text = "Boton: " + i
val param = GridLayout.LayoutParams(
GridLayout.spec(
GridLayout.UNDEFINED, GridLayout.FILL, 1f
),
GridLayout.spec(GridLayout.UNDEFINED, GridLayout.FILL, 1f)
)
button.layoutParams = param
gridLayout.addView(button)
}
I should change import android.widget.GridLayout to import androidx.gridlayout.widget.GridLayout;
And use gridLayout.addView(button) to add the button
I have a drawable that's being displayed in a layout. The drawable has default properties such as color and width. I'm creating a data class to be able to update those when the recycler view is created. The part that fills in the color in the middle is working. But I'm stuck on how to actually update the drawable width and the ImageView margins from the viewHolder.
mydrawable.xml
The layout file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/rect_outline"
android:src="#drawable/mydrawable"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</LinearLayout>
The data class
data class ImageData(
val c: String
val width: Int
val marginLeft : Int
)
MyViewHoler.kt
internal class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: ImageData) {
itemView.rect_outline.setColorFilter(Color.parseColor(item.c))
}
}
first put this into your xml image view component
android:scaleType="fitCenter"
my sugest is use scale with animation to get a good looking for the user
imageView.animate()
.scaleX(scaleValue)
.scaleY(scaleValue)
.setDuration(MOVING_ANIMATION_DURATION)
.start()
imageView.invalidate()
but you can set a new layout params like:
val l = imageView.layoutParams
l.height = value
l.width = value
imageView.layoutParams = l
you can do this way too
val params = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
params.setMargins(0, 20, 0, 40)
params.height = 1
params. width = 1
imageView.layoutParams = params
I try to create a cardView that contains an image and beside that image I want to add two lines of text (vertically stacked on each other). Below is the code I have written to do this (the function returns a cardView). However, in my cardView nothing is appearing. If I remove the linearLayout and the textViews than I get a card which shows the imageView. So I assume I'm doing something wrong with the way I set the linearLayout on my textViews or the way I add my linearLayout to my tableRow.
private fun constructCardView(header: String, info: String) : CardView {
val cardView = CardView(this)
cardView.setPaddingRelative(5,0,0,0)
cardView.radius = 10F
val tableLayout = TableLayout(this)
val layoutParams = TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.MATCH_PARENT, 1.0f)
tableLayout.layoutParams = layoutParams
val tableRow = TableRow(this)
val tableRowParams = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, 1.0f)
tableRow.layoutParams = tableRowParams
val imageView = ImageView(this)
imageView.setImageResource(R.drawable.ic_restaurant_black_24dp)
imageView.minimumHeight = 10
imageView.minimumWidth = 10
val linearLayout = LinearLayout(this)
val linearLayoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
linearLayoutParams.setMargins(3,3,3,3)
linearLayout.layoutParams = linearLayoutParams
linearLayout.orientation = LinearLayout.VERTICAL
val textViewHeader = TextView(this)
val textViewHeaderLayoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
textViewHeaderLayoutParams.setMargins(0, 0, 5, 0)
textViewHeader.layoutParams = textViewHeaderLayoutParams
textViewHeader.text = header
textViewHeader.textSize = 20F
val textViewInfo = TextView(this)
val textViewInfoLayoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
textViewInfoLayoutParams.setMargins(5, 0, 5, 0)
textViewInfo.text = info
textViewInfo.textSize = 12F
textViewInfo.layoutParams = textViewInfoLayoutParams
linearLayout.addView(textViewHeader)
linearLayout.addView(textViewInfo)
tableRow.addView(imageView)
tableRow.addView(linearLayout)
tableLayout.addView(tableRow)
cardView.addView(tableLayout)
cardView.requestLayout()
return cardView
}
Any help would be appreciated.
Just to offer an alternative if using xml is an option, as I think it saves up many many lines of code to get the same job done.
You probably want to use LinearLayout instead of the Tablelayout to stack things vertically or horizontally, as a more versatile approach. For example I used the layout_weight property to define how the rows are split in percentage.
Create an xml file in the layouts folder:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view"
android:layout_gravity="center"
android:layout_width="200dp"
android:layout_height="200dp"
card_view:cardCornerRadius="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView android:layout_width="0dp"
android:layout_weight="0.4"
android:layout_height="match_parent"/>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/header"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v7.widget.CardView>
Then in code:
private fun constructCardView(header: String, info: String) : CardView {
val cardView = LayoutInflater.from(this).inflate(R.layout.cardview, parent, false)
cardView.header.text = header
cardView.info.text = info
return cardView as CardView
}
I have a linear layout like this:
<LinearLayout
android:id="#+id/linearLayoutImages"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="1">
</LinearLayout>
The following function gets a bitmap, sets it to an image view that has been created programmatically, then creates a trash can icon and puts the whole things into a relative layout and finally puts it into the linear layout. But there is a problem, I want the result to be like this:
but the result becomes like this:
Code:
fun setImage(bitmap: Bitmap){
try {
val params = RelativeLayout.LayoutParams(375, 375)
params.addRule(RelativeLayout.ALIGN_PARENT_TOP)
params.setMargins(9,0,9,0)
val imageViewShowPic = ImageView(this)
imageViewShowPic.setLayoutParams(params)
imageViewShowPic.id = View.generateViewId()
imageViewShowPic.requestLayout()
val params2 = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT)
val relativeLayout = RelativeLayout(this)
relativeLayout.setLayoutParams(params2)
relativeLayout.requestLayout()
val params3 = RelativeLayout.LayoutParams(75,75)
params3.addRule(RelativeLayout.BELOW,imageViewShowPic.id)
params3.addRule(RelativeLayout.CENTER_VERTICAL)
val imageButtonDelete = ImageButton(this)
imageButtonDelete.setLayoutParams(params3)
imageButtonDelete.requestLayout()
relativeLayout.addView(imageViewShowPic)
relativeLayout.addView(imageButtonDelete)
linearLayoutImages.addView(relativeLayout)
imageViewShowPic.setImageBitmap(bitmap)
imageButtonDelete.setImageResource(R.drawable.ic_delete)
imageButtonDelete.setOnClickListener {
linearLayoutImages.removeView(relativeLayout)
}
}
catch (ex:Exception)
{
Toast.makeText(this,ex.message,Toast.LENGTH_SHORT).show()
}
}
Update
The linear layout itself is in a horizontal scroll view, if it makes any difference.
<HorizontalScrollView
android:id="#+id/horizontalScrollViewImages"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:padding="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/buttonAddPic">
<LinearLayout
android:id="#+id/linearLayoutImages"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="1"></LinearLayout>
</HorizontalScrollView>
(Posted solution on behalf of the question author).
I finally found the solution myself! I changed the relative layout to a vertical linear layout (I don't know if it matters or not):
val params2 = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
val linearLayout = LinearLayout(this)
linearLayout.setLayoutParams(params2)
linearLayout.orientation = LinearLayout.VERTICAL
linearLayout.requestLayout()
and then set the width of imageButtonDelete to match parent.
val params3 = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
val imageButtonDelete = ImageButton(this)
imageButtonDelete.setLayoutParams(params3)
imageButtonDelete.requestLayout()
imageButtonDelete.setBackgroundColor(Color.TRANSPARENT)
Set (RelativeLayout.CENTER_VERTICAL) to (RelativeLayout.CENTER)
val params3 = RelativeLayout.LayoutParams(75,75)
params3.addRule(RelativeLayout.BELOW,imageViewShowPic.id)
params3.addRule(RelativeLayout.CENTER)
and
android:layout_width="wrap_content" to android:layout_width="match_parent"
<LinearLayout
android:id="#+id/linearLayoutImages"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="1"></LinearLayout>
With the below code you can achieve the desired output.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayoutImages"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:weightSum="1"></LinearLayout>
In Your activity.
try {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(375, 375);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params.setMargins(9, 0, 9, 0);
ImageView imageViewShowPic = new ImageView(this);
imageViewShowPic.setLayoutParams(params);
imageViewShowPic.setId(View.generateViewId());
imageViewShowPic.requestLayout();
RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
RelativeLayout relativeLayout = new RelativeLayout(this);
relativeLayout.setLayoutParams(params2);
relativeLayout.requestLayout();
RelativeLayout.LayoutParams params3 = new RelativeLayout.LayoutParams(75, 75);
params3.addRule(RelativeLayout.BELOW, imageViewShowPic.getId());
params3.topMargin = 30;
params3.addRule(RelativeLayout.CENTER_HORIZONTAL);
ImageButton imageButtonDelete = new ImageButton(this);
imageButtonDelete.setLayoutParams(params3);
imageButtonDelete.requestLayout();
relativeLayout.addView(imageViewShowPic);
relativeLayout.addView(imageButtonDelete);
linearLayoutImages.addView(relativeLayout);
imageViewShowPic.setImageResource(R.drawable.ic_launcher_background);
imageButtonDelete.setImageResource(R.drawable.ic_launcher_background);
} catch (Exception ex) {
Toast.makeText(this, ex.getMessage(), Toast.LENGTH_SHORT).show();
}
OUTPUT