Adding view with weight programmatically to LinearLayout in Kotlin - android

EDIT --- Adding the full code
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.camera.view.PreviewView
android:id="#+id/viewFinder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="#+id/barsContainer"
android:layoutDirection="rtl"
app:layout_constraintBottom_toBottomOf="parent">
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
class MainActivity : AppCompatActivity() {
private var barsIndex = BooleanArray(30) { false }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val viewBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(viewBinding.root)
val layoutParams =
LinearLayout.LayoutParams(0, 80, 1f)
viewBinding.barsContainer.weightSum = (barsIndex.size).toFloat()
for (index in barsIndex.indices) {
val barView = View(this)
// layoutParams.setMargins(60, 60, 60, 60)
barView.setBackgroundColor(Color.parseColor("#FFFFFF"))
barView.layoutParams = layoutParams
viewBinding.barsContainer.addView(barView)
}
}
}
Well I've searched a lot and found a lot of answers regarding this question but still it has not worked for me so far.
I wanna add a number of bars with equal width to a LinearLayout.
this is what I got so far:
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="#+id/barsContainer"
android:layoutDirection="rtl"
app:layout_constraintBottom_toBottomOf="parent">
</androidx.appcompat.widget.LinearLayoutCompat>
and In my Activity.kt:
viewBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(viewBinding.root)
val layoutParams = LinearLayout.LayoutParams(0, 80, 1f)
for (index in barsIndex.indices) {
val barView = View(this)
barView.setBackgroundColor(Color.parseColor("#FFFFFF"))
barView.layoutParams = layoutParams
viewBinding.barsContainer.addView(barView, index)
}
viewBinding.barsContainer.requestLayout()
still it doesn't respect the weight (third parameter) and if I add some width it works but that's not what I want.
I tried both 0 and LinearLayout.LayoutParams.WRAP_CONTENT for the width it still does not work.
adding Margin to children doesn't work either!
Any help would be appreciated

i just edit some of your code to just edit color and height
you just need add this line befor the loop
barsContainer.weightSum = (barsIndex.size).toFloat()
To make sure that he takes the correct weights so that he divides the layout correctly as well
val barsContainer = findViewById<LinearLayoutCompat>(R.id.barsContainer)
val barsIndex = arrayListOf<Int>(1, 2, 3, 4)
barsContainer.weightSum = (barsIndex.size).toFloat()
val layoutParams = LinearLayoutCompat.LayoutParams(0, 150, 1f)
for (index in barsIndex.indices) {
val barView = View(this)
barView.setBackgroundColor(Color.parseColor("#ff${(index+1)*22}00"))
barView.layoutParams = layoutParams
barsContainer.addView(barView,index)
}
val barsIndex = arrayListOf<Int>(1, 2, 3, 4)
barsContainer.weightSum = (barsIndex.size).toFloat()
val layoutParams = LinearLayoutCompat.LayoutParams(0, 150, 1f)
layoutParams.marginEnd=1
layoutParams.marginStart=1
for (index in barsIndex.indices) {
val barView = View(this)
barView.setBackgroundColor(Color.parseColor("#ff${(index+1)*22}00"))
barView.layoutParams = layoutParams
barsContainer.addView(barView,index)
}

Related

animating text view text change using animate layout changes (LayoutTransition.CHANGING)

I've followed a tutorial to animate text change on text view in order to implement (Read more) in comments and such, so far it animates when extending the text but not when collapsing text.
How can i animate on collapse?
gif
fragment
private var extended = false
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val testTextView = view.findViewById<TextView>(R.id.test_text)
val container = view.findViewById<ConstraintLayout>(R.id.text_view_container)
val comment = /*Long comment*/
//animate text change
container.layoutTransition.enableTransitionType(
LayoutTransition.CHANGING
)
if ((comment.length ?: 0) <= 200) {
testTextView.text = comment
} else {
testTextView.text =
comment.substring(
0, if (comment.length < 200) comment.length else 200
)
}
testTextView.setOnClickListener {
extended = !extended
if (extended) {
testTextView.text = comment
} else {
testTextView.text = comment.substring(
0, (if (comment.length < 200) comment.length else 200)
)
}
}
}
XML
<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:id="#+id/fragment_blank_root"
tools:context=".BlankFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/text_view_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/test_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/hello_blank_fragment" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
I tried setting other layout transition but it did not work.
I am expecting it to animate on collapse

Kotlin: Setting width using view.layoutparams.width doesn't work

I am trying to change width of a view programmatically, but it doesn't work, nothing changes. This is the code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/myFragmentLayout"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:orientation="horizontal">
<View
android:id="#+id/myView"
android:layout_width="10dp"
android:layout_height="50dp" />
And in my fragment, I try this:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val views = FragmentMyBinding.bind(view)
views.myView.layoutParams.width = 500
I tried using viewTreeObserver, but still nothing happens:
views.myView.viewTreeObserver.addOnGlobalLayoutListener(
object : OnGlobalLayoutListener {
override fun onGlobalLayout() {
view.viewTreeObserver
.removeOnGlobalLayoutListener(this)
views.myView.updateLayoutParams {
width = 500
}
}
})
Seems like I am calling layoutParams on a wrong layout for some reason
Try this
val params: LinearLayout.LayoutParams = views.myView.layoutParams as LinearLayout.LayoutParams
params.width = 500
views.myView.layoutParams = params

How set all attributes of RelativeLayout Programmatically in Kotlin?

I've created a basic layout in Android in my activity_main.xml for what will eventually be a custom view for a button. It is a relative view with three circles stacked on top of eachother inside it aligned in the centre. The circles change size when the user interacts with them.
I now want to replicate the whole thing purely in Kotlin code, as it will be loaded using data in a database.
I can't figure it out. Heres the manifest...
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<RelativeLayout
android:id="#+id/myContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/button3"
android:layout_width="400dp"
android:layout_height="400dp"
android:layout_centerInParent="true"
app:srcCompat="#drawable/circle"
app:tint="#E60505" />
<ImageView
android:id="#+id/button2"
android:layout_width="400dp"
android:layout_height="400dp"
android:layout_centerInParent="true"
app:srcCompat="#drawable/circle"
app:tint="#FFB700" />
<ImageView
android:id="#+id/button1"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentRight="false"
android:layout_centerInParent="true"
app:srcCompat="#drawable/circle" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Then in Kotlin, all I can find about is LayoutParams for width and height, but where do I set all this stuff for the Relative Layout?
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
which I presume I want to do something like:
class MyContainer : RelativeLayout () {
var button1 = MyButtonClass(someArgs)
var button2 = MyButtonClass(someArgs)
var button3 = MyButtonClass(someArgs)
init {
/// can't find out how to do this bit in Kotlin...
///something like....
this.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT
this.layoutConstraintBottomToBottomOf = PARENT
this.layoutConstraintHorizontalBias = 0.5
///etc...
//then add the circle buttons
this.addView(button3)
this.addView(button2)
this.addView(button1)
}
}
Am I even vagueley on the right track? Any pointers would be really appreciated.
EDIT: Following first answer, I can set layout attributes, but my app is just blank when i try to reproduce my original manifest tree in code. Have I applied this correctly?
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val appContainer = findViewById<ConstraintLayout>(R.id.appContainer)
var buttonContainer = ButtonContainer(this.applicationContext)
appContainer.addView(buttonContainer)
}
}
class ButtonContainer (context: Context) : RelativeLayout(context) {
var button1 = CustomButton(context)
val buttonLayoutParams by lazy { ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT).apply {
bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
startToStart = ConstraintLayout.LayoutParams.PARENT_ID
topToTop = ConstraintLayout.LayoutParams.PARENT_ID
endToEnd = ConstraintLayout.LayoutParams.PARENT_ID
horizontalBias = 0.5F
}
}
override fun onFinishInflate() {
super.onFinishInflate()
this.layoutParams = buttonLayoutParams
this.addView(button1)
}
}
class CustomButton(context: Context) : ImageView(context) {
val layoutParams by lazy { RelativeLayout.LayoutParams(60, 60).apply {
addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE)
}
}
override fun onFinishInflate() {
super.onFinishInflate()
setLayoutParams(layoutParams)
setBackgroundResource(squibcircle)
}
}
You need to cast LayoutParams as ConstraintLayout.LayoutParams to set those properties like below
class ButtonContainer(context: Context) : RelativeLayout(context) {
var button1 = CustomButton(context)
val buttonLayoutParams by lazy { ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT).apply {
bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
startToStart = ConstraintLayout.LayoutParams.PARENT_ID
topToTop = ConstraintLayout.LayoutParams.PARENT_ID
endToEnd = ConstraintLayout.LayoutParams.PARENT_ID
horizontalBias = 0.5F
}
}
override fun onFinishInflate() {
this.layoutParams = buttonLayoutParams
this.addView(button1)
}
}

Screenshot of a View is not has the same size as the view?

So, I'm trying to blur out my ContraintLayout what approach I took is
Take a screenshot of the root view.
Add an ImageView in the root view with layout param MATCH_PARENT and MATCH_PARENT.
Blur that screenshot
Set the screenshot bitmap to this ImageView.
But it's not working as expected. Any help would be appreciated.
Here is some relevant code I'm using.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val imageView = ImageView(this)
val param = ConstraintLayout.LayoutParams(
ConstraintLayout.LayoutParams.MATCH_PARENT,
ConstraintLayout.LayoutParams.MATCH_PARENT
)
imageView.layoutParams = param
val bit = convertViewToBitmap(root)
val blurred = blur(bit,25F)
imageView.setImageBitmap(blurred)
root.addView(imageView)
}
To get the screenshot of a View
private fun convertViewToBitmap(view: View): Bitmap {
val spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
view.measure(spec, spec)
view.layout(0, 0, view.measuredWidth, view.measuredHeight)
val b = Bitmap.createBitmap(view.measuredWidth, view.measuredHeight,
Bitmap.Config.ARGB_8888)
val c = Canvas(b)
//c.translate((-view.scrollX).toFloat(), (-view.scrollY).toFloat())
view.draw(c)
return b
}
To blur that ScreenShot
var times = 0
fun blur(bitmap: Bitmap, radius: Float): Bitmap? {
val renderScript = RenderScript.create(this)
val blurredBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
val input: Allocation = Allocation.createFromBitmap(
renderScript,
blurredBitmap,
Allocation.MipmapControl.MIPMAP_FULL,
Allocation.USAGE_SHARED
)
val output: Allocation = Allocation.createTyped(renderScript, input.type)
// Load up an instance of the specific script that we want to use.
ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript)).apply {
setInput(input)
setRadius(radius)
forEach(output)
}
output.copyTo(blurredBitmap)
if (times < 5) {
times += 1
blur(blurredBitmap, radius)
}
return blurredBitmap
}
Here is the XML file
<?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/root"
android:background="#android:color/white"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="30sp"
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.20" />
</androidx.constraintlayout.widget.ConstraintLayout>
Here is the result
Instead of taking the screenshot of the view and blurring it. try this:
Blur the TextView using BlueMaskFilter
float radius = yourTextView.getTextSize() / 3;
BlurMaskFilter filter = new BlurMaskFilter(radius, BlurMaskFilter.Blur.NORMAL);
yourTextView.getPaint().setMaskFilter(filter);
Convert the blurred TextView to BitMap and set it to the ImageView bitmap

CardView not clickable

In MainActivity, I have a pie chart, where the libary get from GitHub - PhilJay/MPAndroidChart: A powerful Android chart view. I add the pie chart into cardView.When cardView is clicked, toast suppose to be displayed. But the onClickListener not working at all.
MainActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
showChart()
cardView.setOnClickListener {
Toast.makeText(application,"clicked",Toast.LENGTH_LONG).show()
}
}
private fun showChart() {
chart.setUsePercentValues(true)
chart.description.isEnabled = false
chart.center
chart.extraRightOffset = 20f
chart.isDrawHoleEnabled = true
chart.setHoleColor(Color.WHITE)
chart.setTransparentCircleColor(Color.WHITE)
chart.setTransparentCircleAlpha(10)
chart.holeRadius = 58f
chart.transparentCircleRadius = 46f
chart.setDrawCenterText(true)
chart.rotationAngle = 0f
chart.isRotationEnabled = true
chart.animateY(1400, Easing.EaseInOutQuad)
val l = chart.legend
l.verticalAlignment = Legend.LegendVerticalAlignment.CENTER
l.horizontalAlignment = Legend.LegendHorizontalAlignment.LEFT
l.orientation = Legend.LegendOrientation.VERTICAL
l.setDrawInside(false)
l.xOffset = 50f
chart.setEntryLabelColor(Color.WHITE)
chart.setEntryLabelTextSize(12f)
setData(3,5)
}
private fun setData(numOpen: Int, numInProgress: Int) {
val entries = ArrayList<PieEntry>()
val colors = ArrayList<Int>()
if (numOpen > 0) {
entries.add(PieEntry(numOpen.toFloat(), "Open"))
colors.add(ColorTemplate.rgb("#F44336"))
}
if (numInProgress > 0) {
entries.add(PieEntry(numInProgress.toFloat(), "Progress"))
colors.add(ColorTemplate.rgb("#2196F3"))
}
val dataSet = PieDataSet(entries, "Status")
dataSet.sliceSpace = 3f
dataSet.iconsOffset = MPPointF(0f, 40f)
dataSet.selectionShift = 5f
dataSet.colors = colors
val data = PieData(dataSet)
data.setValueFormatter(PercentFormatter(chart))
data.setValueTextSize(11f)
data.setValueTextColor(Color.WHITE)
chart.data = data
// undo all highlights
chart.highlightValues(null)
chart.invalidate()
}
}
main_activity
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:id="#+id/cardView"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:layout_marginRight="15dp">
<com.github.mikephil.charting.charts.PieChart
android:background="#color/colorPrimary"
android:id="#+id/chart"
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_gravity="center_horizontal|center_vertical"/>
</android.support.v7.widget.CardView>
</LinearLayout>
</ScrollView>
Image
As the PieChart fully absorbing the click to interact with the chart elements, the click listener defined in the parent will not be called. Even If you set an OnClickListener to PieChart, it won't work. The solution to this problem is to set onChartGestureListener to PieChart and call your method from onChartSingleTapped.
Example
override fun onCreate(savedInstanceState: Bundle?) {
...
cardView.setOnClickListener {
doThis();
}
chart.onChartGestureListener = object : OnChartGestureListener {
override fun onChartSingleTapped(me: MotionEvent?) {
doThis()
}
}
}
fun doThis(){
// your code goes here
}

Categories

Resources