I am having some problems getting the result I want using RelativeLayout
, also wondering if I should also use LinearLayout
at the same time. Here is my code:
package me.soft.myapp
import android.content.Context
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.TypedValue
import android.view.Gravity
import android.view.View
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.ScrollView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
class MainActivity : AppCompatActivity() {
lateinit private var constraintLayout: ConstraintLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
constraintLayout = this.findViewById(R.id.activity_main)
val relatLayOut = RelativeLayout(this)
relatLayOut.id = View.generateViewId()
val rllyLOP = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT)
relatLayOut.layoutParams = rllyLOP
constraintLayout.addView(relatLayOut)
// We define 2 colored stripes and one scroll view.
val bannerOne = stripe("Hello wonderful world of yours ...",
Color.rgb(0xEE,0xEE,0x22))
val bannerTwo = stripe("The purpose of our lives is to be happy.",
Color.rgb(0x22,0xEE,0xEE))
val scrolZone = scrollBlock(longNumberString(1000))
// We add them to the global layout.
relatLayOut.addView(bannerOne)
relatLayOut.addView(bannerTwo)
relatLayOut.addView(scrolZone)
// Set the layout and order of the components:
val layoutOption = 2//1
if (layoutOption == 1) {
setViewBelow(bannerTwo,bannerOne)
setViewBelow(scrolZone,bannerTwo)
}
if (layoutOption == 2) {
setViewBelow(scrolZone, bannerOne)
setViewBelow(bannerTwo, scrolZone)
}
}
fun Int.dpToPixels(context: Context):Float = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,this.toFloat(),context.resources.displayMetrics
)
fun stripe(display:String, bgc: Int): RelativeLayout {
val lnlyLOP = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT)
val lnlyOut = RelativeLayout(this)
lnlyOut.id = View.generateViewId()
lnlyOut.gravity = Gravity.CENTER
lnlyOut.layoutParams = lnlyLOP
lnlyOut.setBackgroundColor(bgc)
val theLabel = TextView(this)
theLabel.text = display
theLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, 25.dpToPixels(this))
theLabel.gravity = Gravity.CENTER
lnlyOut.addView(theLabel)
return lnlyOut
} /* End of stripe */
fun scrollBlock(display:String): ScrollView {
val scrolViw = ScrollView(this)
scrolViw.id = View.generateViewId()
val rllyLOP = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
)
scrolViw.layoutParams = rllyLOP
val theLabel = TextView(this)
theLabel.text = display
scrolViw.addView(theLabel)
return scrolViw
} /* End of scrollBlock */
fun setViewBelow(theView: View, referView: View) { // To set theView below referView.
val memoLOP = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT)
memoLOP.addRule(RelativeLayout.BELOW, referView.id)
theView.layoutParams = memoLOP
} /* End of setViewBelow */
fun longNumberString(n:Int): String { // To make a long string of numbers.
if (n<0) return ""
var resultStr = "0"
for (i in 1..n) {resultStr = "-$i"}
return resultStr
} /* End of longNumberString */
}
This code is working as I expect when I use layoutOption = 1. But not when I use layoutOption = 2.
Here what I get on the device for layoutOption = 1 :
Here what I get on the device for layoutOption = 2 :
But here what I expect for layoutOption = 2 :
Obviously I am doing something wrong for the result I want with layoutOption = 2.
Can anyone see where the mistake is?
Here is the XML file, just in case:
<?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/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />
CodePudding user response:
Since you are using RelativeLayout, you could do something like this to achieve your desired results:
a. Make your bannerTwo bottom align to Parent bottom using LayoutParams#alignParentBottom
b. Make your ScrollView Bottom to be Top of bannerTwo using LayoutParams#layout_above
c. Similarly Make your ScrollView Top to be Bottom of bannerOne using LayoutParams#layout_below
This will lock in the size of the ScrollView between the two banners while making the bannerOne and bannerTwo visible on screen. Hope that helps.
CodePudding user response:
Thanks to the tips provided in Pratik K's answer; here is how I finally solved the problem from the code in the post. I replaced the following lines of code:
if (layoutOption == 2) {
setViewBelow(scrolZone, bannerOne)
setViewBelow(bannerTwo, scrolZone)
}
by the ones below:
if (layoutOtion == 2) {
stickViewAtBottom(bannerTwo)
setViewBetween(scrolZone,bannerOne,bannerTwo)
}
Where the two new functions stickViewAtBottom() and setViewBetween() are defined as:
fun stickViewAtBottom(theView: View) { // To set theView at the bottom of its parent.
val memoLOP = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT)
val parentID = (theView.parent as View).id
memoLOP.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, parentID)
theView.layoutParams = memoLOP
} /* End of stickViewAtBottom */
fun setViewBetween(theView: View, aboveView: View, beneathView: View) {
val memoLOP = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT)
memoLOP.addRule(RelativeLayout.BELOW, aboveView.id)
memoLOP.addRule(RelativeLayout.ABOVE, beneathView.id)
theView.layoutParams = memoLOP
} /* End of setViewBetween */