Function to animate an ImageView in a RecyclerView - android
To forward my application, i need a function that will rotate an imageView in a recyclerView.
The recyclerView is one of 3 recyclerviews that are already working well, and are clickable through a cardView.
shortvideo there:
https://mega.nz/#!W6AyAYaY!07WG8kr_POYiGsgt0yja6fk8RaclZLw2-MiMFrmEQmk
I created Classes with a few members, which permit to know the state of the objects.
I am newbie in Android programmation, and it was difficult for me to make these recyclerView working well :-)
7 April : i finally succeeded to implement my function
but the result is weird !
can see there :
https://mega.nz/#!DzI2iaiB!VBG9Ex4TZlAsoUYPSRhXXMP4weH-9hXyjbqF1nCRyeA
There is an imageView which is rotating, but this is the left one, not the clicked one, and there is a mix, a swap between pictures.
My question is : are the imageViews clickable and focusable like cardViews ?
if so i can try to make the imageView focusable and clickable (actually the cardView is... )
What about the index is recyclerViews ? isn't it the cardview which is clicked which has the index ? or the left one in the screen ?
I am puzzled :-)
Following: the layout with CardView and imageView; MainActivity where i tried to write the function; and the Adapter for the Top RecyclerView where the function is supposed to
rotate (180 °) the imageView at the index ( index, tag and position )
no change about that xml file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView
android:id="#+id/flag_card_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:focusable="true"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground">
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="#+id/flagcountry"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintDimensionRatio="W,55:100"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginLeft="2dp"/>
<TextView
android:id="#+id/flagname"
android:layout_width="6dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toRightOf="#id/flagcountry"
android:layout_centerVertical="true"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
under new kt file
package training.geography.triplerecyclerview
import android.provider.Settings.Global.getString
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.cardview.widget.CardView
import androidx.recyclerview.widget.RecyclerView
class FlagAdapter(val flagcountrylist: List<FlagCard>,
val flagitemClickListener : View.OnClickListener
//val flagitemOnLongClickListener : View.OnLongClickListener
):
RecyclerView.Adapter<FlagAdapter.FlagViewHolder> () {
class FlagViewHolder(flagView: View) : RecyclerView.ViewHolder(flagView) {
val flagcardView = flagView.findViewById<CardView>(R.id.flag_card_view)
val flagcountry = flagView.findViewById<ImageView>(R.id.flagcountry)
val flagname = flagView.findViewById<TextView>(R.id.flagname)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
FlagViewHolder {
val inflater = LayoutInflater.from(parent.context)
val viewItem = inflater.inflate(R.layout.item_flag, parent, false)
return FlagViewHolder(viewItem)
}
override fun onBindViewHolder(flagholder: FlagViewHolder, position: Int) {
//val flagcountry: String = flagcountrylist.FlagCard.flagimage[position]
//var flagimageList: List<String> = flagcountrylist.map { it.flagimage }
var flagsouthList: List<String> = flagcountrylist.map { it.flagsouth }
var iflagsouth = flagsouthList[position]
flagholder.flagname.text = iflagsouth
flagholder.flagcardView.tag = position
flagholder.flagcardView.setOnClickListener(flagitemClickListener)
//flagholder.flagcardView.setOnLongClickListener(itemOnLongClickListener)
when (position){
0 -> flagholder.flagcountry.setImageResource(R.drawable.afgcol)
1 -> flagholder.flagcountry.setImageResource(R.drawable.argsvk)
2 -> flagholder.flagcountry.setImageResource(R.drawable.armche)
3 -> flagholder.flagcountry.setImageResource(R.drawable.auttgo)
4 -> flagholder.flagcountry.setImageResource(R.drawable.azepry)
5 -> flagholder.flagcountry.setImageResource(R.drawable.bhrtur)
6 -> flagholder.flagcountry.setImageResource(R.drawable.bratls)
7 -> flagholder.flagcountry.setImageResource(R.drawable.bwasur)
8 -> flagholder.flagcountry.setImageResource(R.drawable.cafbtn)
9 -> flagholder.flagcountry.setImageResource(R.drawable.critun)
10 -> flagholder.flagcountry.setImageResource(R.drawable.pandza)
11 -> flagholder.flagcountry.setImageResource(R.drawable.persau)
12 -> flagholder.flagcountry.setImageResource(R.drawable.svnago)
13 -> flagholder.flagcountry.setImageResource(R.drawable.sweben)
14 -> flagholder.flagcountry.setImageResource(R.drawable.tcdgbr)
15 -> flagholder.flagcountry.setImageResource(R.drawable.thabol)
16 -> flagholder.flagcountry.setImageResource(R.drawable.tjkdeu)
17 -> flagholder.flagcountry.setImageResource(R.drawable.tkmbel)
18 -> flagholder.flagcountry.setImageResource(R.drawable.tzablz)
19 -> flagholder.flagcountry.setImageResource(R.drawable.ukrcmr)
20 -> flagholder.flagcountry.setImageResource(R.drawable.uryblr)
21 -> flagholder.flagcountry.setImageResource(R.drawable.venbgd)
22 -> flagholder.flagcountry.setImageResource(R.drawable.vnmbfa)
23 -> flagholder.flagcountry.setImageResource(R.drawable.yembih)
24 -> flagholder.flagcountry.setImageResource(R.drawable.zmbchl)
25 -> flagholder.flagcountry.setImageResource(R.drawable.zwealb)
}
//var iflagcard:String = imagelist[position]
//holder.flagcountry.setImageResource(iflagcard)
}
override fun getItemCount(): Int {
return flagcountrylist.size
}
}
---------------------------------------
//under new MainActivity file with function modified
// i don't know what to do with the variable
// flagtempup, i use it to set the string in
// iflagtrigramdown, and i have te warning variable not used...
package training.geography.triplerecyclerview
import android.nfc.Tag
import android.os.Bundle
import android.view.View
import android.view.View.OnClickListener
import android.view.animation.Animation
import android.view.animation.RotateAnimation
import android.widget.ImageView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.cardview.widget.CardView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.item_flag.*
data class FlagCard(var flagtrigramup: String, var flagtrigramdown: String,
var flagimage: String, var flagsouth: String, var rotationpossible: Boolean=(true))
data class CountryCard(val countrytrigram: String, val description: String)
data class MapCard(var map_left_up: String,
var map_right_up: String,
var map_left_down: String,
var map_right_down: String,
var maps_img: String,
var mapnorth: String)
class MainActivity : AppCompatActivity(), OnClickListener {
var afg_col = FlagCard("col", "afg", "afgcol", "afg", true)
var arg_svk = FlagCard("arg", "svk", "argsvk", "svk", true)
var arm_che = FlagCard("che", "arm", "armche", "arm", true)
var aut_tgo = FlagCard("tgo", "aut", "auttgo", "aut", true)
var aze_pry = FlagCard("aze", "pry", "azepry", "pry", true)
var bhr_tur = FlagCard("tur", "bhr", "bhrtur", "bhr", true)
var bra_tls = FlagCard("tls", "bra", "bratls", "bra", true)
var bwa_sur = FlagCard("sur", "bwa", "bwasur", "bwa", true)
var caf_btn = FlagCard("btn", "caf", "cafbtn", "caf", true)
var cri_tun = FlagCard("cri", "tun", "critun", "tun", true)
var pan_dza = FlagCard("pan", "dza", "pandza", "dza", true)
var per_sau = FlagCard("per", "sau", "persau", "sau", true)
var svn_ago = FlagCard("svn", "ago", "svnago", "ago", true)
var swe_ben = FlagCard("swe", "ben", "sweben", "ben", true)
var tcd_gbr = FlagCard("tcd", "gbr", "tcdgbr", "gbr", true)
var tha_bol = FlagCard("tha", "bol", "thabol", "bol", true)
var tjk_deu = FlagCard("tjk", "deu", "tjkdeu", "deu", true)
var tkm_bel = FlagCard("tkm", "bel", "tkmbel", "bel", true)
var tza_blz = FlagCard("tza", "blz", "tzablz", "blz", true)
var ukr_cmr = FlagCard("ukr", "cmr", "ukrcmr", "cmr", true)
var ury_blr = FlagCard("ury", "blr", "uryblr", "blr", true)
var ven_bgd = FlagCard("ven", "bgd", "venbgd", "bgd", true)
var vnm_bfa = FlagCard("vnm", "bfa", "vnmbfa", "bfa", true)
var yem_bih = FlagCard("yem", "bih", "yembih", "bih", true)
var zmb_chl = FlagCard("zmb", "chl", "zmbchl", "chl", true)
var zwe_alb = FlagCard("zwe", "alb", "zwealb", "alb", true)
var afg = CountryCard("afg", "afg")
var ago = CountryCard("ago", "ago")
var alb = CountryCard("alb", "alb")
var arg = CountryCard("arg", "arg")
var arm = CountryCard("arm", "arm")
var aut = CountryCard("aut", "aut")
var aze = CountryCard("aze", "aze")
var bel = CountryCard("bel", "bel")
var bfa = CountryCard("bfa", "bfa")
var bhr = CountryCard("bhr", "bhr")
var bih = CountryCard("bih", "bih")
var blz = CountryCard("blz", "blz")
var bol = CountryCard("bol", "bol")
var bra = CountryCard("bra", "bra")
var btn = CountryCard("btn", "btn")
var bwa = CountryCard("bwa", "bwa")
var caf = CountryCard("caf", "caf")
var che = CountryCard("che", "che")
var chl = CountryCard("chl", "chl")
var cmr = CountryCard("cmr", "cmr")
var col = CountryCard("col", "col")
var cri = CountryCard("cri", "cri")
var deu = CountryCard("deu", "deu")
var gbr = CountryCard("gbr", "gbr")
var pan = CountryCard("pan", "pan")
var per = CountryCard("per", "per")
var pry = CountryCard("pry", "pry")
var sau = CountryCard("sau", "sau")
var sur = CountryCard("sur", "sur")
var svk = CountryCard("svk", "svk")
var svn = CountryCard("svn", "svn")
var swe = CountryCard("swe", "swe")
var tcd = CountryCard("tcd", "tcd")
var tgo = CountryCard("tgo", "tgo")
var tha = CountryCard("tha", "tha")
var tjk = CountryCard("tjk", "tjk")
var tkm = CountryCard("tkm", "tkm")
var tls = CountryCard("tls", "tls")
var tun = CountryCard("tun", "tun")
var tur = CountryCard("tur", "tur")
var tza = CountryCard("tza", "tza")
var ukr = CountryCard("ukr", "ukr")
var ury = CountryCard("ury", "ury")
var ven = CountryCard("ven", "ven")
var vnm = CountryCard("vnm", "vnm")
var yem = CountryCard("yem", "yem")
var zmb = CountryCard("zmb", "zmb")
var zwe = CountryCard("zwe", "zwe")
var arm_bol_gbr_ago = MapCard("arm", "bol", "gbr", "ago", "bol", "armbolgbrago")
var aze_bra_aut_ben = MapCard("aze", "bra", "aut", "ben", "bra", "azebraautben")
var bfa_blr_col_bgd = MapCard("bfa", "blr", "col", "bgd", "blr", "bfablrcolbgd")
var bwa_bel_bhr_chl = MapCard("bwa", "bel", "bhr", "chl", "bel", "bwabelbhrchl")
var caf_afg_alb_arg = MapCard("caf", "afg", "alb", "arg", "afg", "cafafgalbarg")
var che_tkm_tur_sur = MapCard("che", "tkm", "tur", "sur", "tkm", "chetkmtursur")
var cri_cmr_btn_bih = MapCard("cri", "cmr", "btn", "bih", "cmr", "cricmrbtnbih")
var sau_blz_deu_dza = MapCard("sau", "blz", "deu", "dza", "blz", "saublzdeudza")
var svn_tha_tcd_pry = MapCard("svn", "tha", "tcd", "pry", "tha", "svnthatcdpry")
var swe_tls_tgo_per = MapCard("swe", "tls", "tgo", "per", "tls", "swetlstgoper")
var tjk_pan_svk_tza = MapCard("tjk", "pan", "svk", "tza", "pan", "tjkpansvktza")
var ven_zwl_yem_ukr = MapCard("ven", "zwl", "yem", "ukr", "zwl", "venzwlyemukr")
var zmb_tur_ury_vnm = MapCard("zmb", "tur", "ury", "vnm", "tur", "zmbtururyvnm")
var flagcountrylist = listOf<FlagCard>(
afg_col,
arg_svk,
arm_che,
aut_tgo,
aze_pry,
bhr_tur,
bra_tls,
bwa_sur,
caf_btn,
cri_tun,
pan_dza,
per_sau,
svn_ago,
swe_ben,
tcd_gbr,
tha_bol,
tjk_deu,
tkm_bel,
tza_blz,
ukr_cmr,
ury_blr,
ven_bgd,
vnm_bfa,
yem_bih,
zmb_chl,
zwe_alb
)
val flagadapter = FlagAdapter(flagcountrylist, this)
var countryList = listOf<CountryCard>(
afg,
ago,
alb,
arg,
arm,
aut,
aze,
bel,
bfa,
bhr,
bih,
blz,
blz,
bol,
bra,
btn,
bwa,
caf,
che,
chl,
cmr,
col,
cri,
deu,
gbr,
pan,
per,
pry,
sau,
sur,
svk,
svn,
swe,
tcd,
tgo,
tha,
tjk,
tkm,
tls,
tun,
tur,
tza,
ukr,
ury,
ven,
vnm,
yem,
zmb,
zwe
)
val countryadapter = CountryAdapter(countryList)
var mapcountrylist = listOf<MapCard>(
arm_bol_gbr_ago,
aze_bra_aut_ben,
bfa_blr_col_bgd,
bwa_bel_bhr_chl,
caf_afg_alb_arg,
che_tkm_tur_sur,
cri_cmr_btn_bih,
sau_blz_deu_dza,
svn_tha_tcd_pry,
swe_tls_tgo_per,
tjk_pan_svk_tza,
ven_zwl_yem_ukr,
zmb_tur_ury_vnm
)
val mapadapter = MapAdapter(mapcountrylist)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val flagsrecyclerView = findViewById<RecyclerView>(R.id.flagsRecyclerView)
flagsrecyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL, false)
flagsrecyclerView.adapter = flagadapter
val countryrecyclerView = findViewById<RecyclerView>(R.id.countriesRecyclerView)
countryrecyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL, false)
countryrecyclerView.adapter = countryadapter
val maprecyclerView = findViewById<RecyclerView>(R.id.mapsRecyclerView)
maprecyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL, false)
maprecyclerView.adapter = mapadapter
}
fun rotateFlagCard (flagCard: FlagCard, position: Int) : FlagCard {
var flagtrigramuplist: List<String> = flagcountrylist.map{it.flagtrigramup }
var iflagtrigramup : String = flagtrigramuplist[position]
var flagimagelist = flagcountrylist.map{it.flagimage}
var iflagimage = flagimagelist[position]
var flagsouthlist = flagcountrylist.map { it.flagsouth }
var iflagsouth = flagsouthlist[position]
var rotationpossiblelist : List<Boolean> = flagcountrylist.map{ it.rotationpossible }
var irotationpossible = rotationpossiblelist[position]
var iflagimageView = findViewById<ImageView>(R.id.flagcountry)
when (position) {
0 -> iflagimageView.setImageResource(R.drawable.afgcol)
1 -> iflagimageView.setImageResource(R.drawable.argsvk)
2 -> iflagimageView.setImageResource(R.drawable.armche)
3 -> iflagimageView.setImageResource(R.drawable.auttgo)
4 -> iflagimageView.setImageResource(R.drawable.azepry)
5 -> iflagimageView.setImageResource(R.drawable.bhrtur)
6 -> iflagimageView.setImageResource(R.drawable.bratls)
7 -> iflagimageView.setImageResource(R.drawable.bwasur)
8 -> iflagimageView.setImageResource(R.drawable.cafbtn)
9 -> iflagimageView.setImageResource(R.drawable.critun)
10 -> iflagimageView.setImageResource(R.drawable.pandza)
11 -> iflagimageView.setImageResource(R.drawable.persau)
12 -> iflagimageView.setImageResource(R.drawable.svnago)
13 -> iflagimageView.setImageResource(R.drawable.sweben)
14 -> iflagimageView.setImageResource(R.drawable.tcdgbr)
15 -> iflagimageView.setImageResource(R.drawable.thabol)
16 -> iflagimageView.setImageResource(R.drawable.tjkdeu)
17 -> iflagimageView.setImageResource(R.drawable.tkmbel)
18 -> iflagimageView.setImageResource(R.drawable.tzablz)
19 -> iflagimageView.setImageResource(R.drawable.ukrcmr)
20 -> iflagimageView.setImageResource(R.drawable.uryblr)
21 -> iflagimageView.setImageResource(R.drawable.venbgd)
22 -> iflagimageView.setImageResource(R.drawable.vnmbfa)
23 -> iflagimageView.setImageResource(R.drawable.yembih)
24 -> iflagimageView.setImageResource(R.drawable.zmbchl)
25 -> iflagimageView.setImageResource(R.drawable.zwealb)
else -> throw AssertionError()
}
if (irotationpossible)
{
iflagimageView.animate().apply {
rotationBy(180f)
duration = 1000L
start()
// permutation of values north south
var flagtrigramdownlist :List<String> = flagcountrylist.map{it.flagtrigramdown}
var iflagtrigramdown : String = flagtrigramdownlist[position]
var flagtempup: String = iflagtrigramup
var flagtempdown: String = iflagtrigramdown
iflagtrigramup = iflagsouth
//flagtempdown = flagtempup
iflagtrigramdown = flagtempup
var iflagCard = FlagCard( iflagtrigramup, iflagtrigramdown, iflagimage, iflagsouth, irotationpossible )
return iflagCard
}
} else {
return flagCard
//Toast.makeText(this, "flag already matched country", Toast.LENGTH_LONG).show()
}
}
override fun onClick(flagcardView: View) {
if (flagcardView.tag != null) {
val index = flagcardView.tag as Int
var flagsouthList: List<String> = flagcountrylist.map{it.flagsouth }
val flags = flagsouthList[index]
Toast.makeText(this, "country : ${flags}", Toast.LENGTH_LONG).show()
var flagcard:FlagCard = flagcountrylist[index]
rotateFlagCard (flagcard, index)
}
}
}
It looks like nobody is interested by what is possible to do with RecyclerViews...
I still have the problem that when an imageView is clicked, this is the one at left which is rotating ! i can't understand what happens, examination in debugger shows the variables are ok, the index is position and do not change...
I tried to apply rotate function to the cardView, same result !
I modified the code in the function and replace the flagCard by iflagCard if rotation was done (because two flags, one up, one down, and of course the FlagCard is different... )
Here the new code :
if (irotationpossible)
{
iflagcardView.animate().apply {
rotationBy(180f)
duration = 1000L
start()
// permutation of values north south
var flagtrigramdownlist :List<String> = flagcountrylist.map{it.flagtrigramdown}
var iflagtrigramdown : String = flagtrigramdownlist[position]
var flagtempup: String = iflagtrigramup
var flagtempdown: String = iflagtrigramdown
iflagtrigramup = iflagsouth
iflagsouth = flagtempup
iflagtrigramdown = flagtempup
var iflagCard = FlagCard( iflagtrigramup, iflagtrigramdown, iflagimage, iflagsouth, irotationpossible )
//flagcountrylist.toSet(position, iflagCard)
//abstract operator fun set(position: Int, iflagCard: FlagCard): FlagCard
flagcountrylist.removeAt(position)
flagcountrylist.add(position, iflagCard)
return iflagCard
}
} else {
return flagCard
//Toast.makeText(this, "flag already matched country", Toast.LENGTH_LONG).show()
}
my question is now about the set function for mutableListOf in Kotlin :
i tried to use " abstract operator fun set(index: Int, element: E): E "
but couldn't build because of abstract !
Is there any other way than my solution to remove then add at the same index ?
Is there any experimented developper curious about the strange rotation in that app ?
https://www.youtube.com/watch?v=d9o7fttLBxk
Why not the image with right index ?
Related
How to add data to Array list that is linked to a recycler view [closed]
Closed. This question needs debugging details. It is not currently accepting answers. Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question. Closed 11 months ago. Improve this question Good day. So I am trying to add data to my tables by an action. I currently have it is static and would like to know the best way to insert data. My end goal is for a driver to be selected and based on the driver name that was selected it will pull that drivers deliveries for the day. I have seen post about fragments but don't know if that will be relevant to me. MainActivity package com.dispatch.tripsheet import android.os.Bundle import android.view.View import android.widget.* import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { private var dbHandler: DBHandler? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) recyclerViewTripsheetlist.layoutManager = LinearLayoutManager(this) recyclerViewTripsheetlist.adapter = TableViewAdapter(Tripsheetlist) //This is for the drivers. Drivers still need to be pulled from the database val list : MutableList<String> = ArrayList() list.add("Deon") list.add("Leon") list.add("David") list.add("Dick") list.add("Jim") list.add("Harry") val adapter = ArrayAdapter( this, androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, list) val spinner: Spinner = findViewById(R.id.spnDriver) spinner.adapter = adapter spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{ override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) { val item :String = list[p2] Toast.makeText(this#MainActivity, "Driver $item selected", Toast.LENGTH_SHORT).show() } override fun onNothingSelected(p0: AdapterView<*>?) { //empty } //insert code that activates data pull of tripsheet for driver= actifavte by method the class/object that activates the data pull. so datapuul(Driver) } limitDropDownHeight(spinner) //drivers end val btnLoadData: Button = findViewById(R.id.btnLoadData) weightsum(tvTotalweight, Tripsheetlist) totaldelNotes(tvTotaldelv,Tripsheetlist) setData(btnLoadData,Tripsheetlist) } val Tripsheetlist = ArrayList<DataModel>().apply { add(DataModel(190617, 182832, "", 0,"", "","")) // Need one row for dummy data. Gets removed so chance wont be seen. add(DataModel(190617, 182832, "Jcorp", 100,"Delivery done", "Delivery not done","")) add(DataModel(190617, 182833, "Honda", 100,"No exceptions", "Exceptions","")) add(DataModel(190617, 182832, "Everflu", 100,"100%", "50%","")) add(DataModel(190617, 182832, "Panado", 300,"OK", "NO","")) add(DataModel(190617, 182832, "Gheiters", 100,"Success", "Failed","")) add(DataModel(190617, 182832, "John", 300,"Yes", "No","")) // need to change from hardcoded text to input //these values will change from sql input var a = 10000 var b = 10000 var c = "Absa" var d = 50 var e = "No exceptions" var f = "Exceptions" var g = "" // value to changes based on data size. var x: Int = 29 for (i in 20..x) { add(DataModel(a,b,c,d,e,f,g)) a++ } // }) } //setData is not 100% ready private fun setData(btnLoadData: Button, Tripsheetlist: ArrayList<DataModel>) { btnLoadData.setOnClickListener(View.OnClickListener { var x: Int = 2 for (i in 3..6) { //does not work this.Tripsheetlist[x].WOrder = 20022 this.Tripsheetlist[x].DElNote = 20022 this.Tripsheetlist[x].Company = "FNB" this.Tripsheetlist[x].Weight = 20 this.Tripsheetlist[x].Button1 = "No exceptions" this.Tripsheetlist[x].Button2 = "Exceptions" this.Tripsheetlist[x].tvdone = "" x++ } btnLoadData.setBackgroundColor(getColor(R.color.green)) } }) } //works fun weightsum(args: TextView, Tripsheetlist: ArrayList<DataModel>) { var totweight: Int = 0 var sum: Int = 0 for (i in 0 until Tripsheetlist.size -1) { sum += Tripsheetlist[i].Weight } totweight = sum tvTotalweight.setText("Total Weight: " + totweight + "kg") } //works fun totaldelNotes(tvTotaldelv: TextView?, Tripsheetlist: ArrayList<DataModel>) { var totnotes: Int = 1 var sum: Int = 0 // var input: String totnotes = Tripsheetlist.size -1 tvTotaldelv?.setText("Total Delivery Notes: " +totnotes) } //works fun limitDropDownHeight(spinner: Spinner){ val popup = Spinner::class.java.getDeclaredField( "mPopup") popup.isAccessible = true val popupWindow = popup.get(spinner)as ListPopupWindow popupWindow.height = (200 * resources.displayMetrics.density).toInt() } } TableViewAdapter package com.dispatch.tripsheet import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.table_list_item.view.* class TableViewAdapter( var Tripsheetlist: List<DataModel> = emptyList()) : RecyclerView.Adapter<TableViewAdapter.RowViewHolder>() { // var dataItems: List<DataModel> = emptyList() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RowViewHolder { val itemView = LayoutInflater.from(parent.context).inflate(R.layout.table_list_item, parent, false) return RowViewHolder(itemView) } override fun getItemCount(): Int { return Tripsheetlist.size// + 1 // one more to add header row } private fun updateData(data: List<DataModel>) { Tripsheetlist = data notifyDataSetChanged() } override fun onBindViewHolder(holder: RowViewHolder, position: Int) { val rowPos = holder.adapterPosition val dataItem = Tripsheetlist[position] if (rowPos == 0) { // Header Cells. Main Headings appear here holder.itemView.apply { setHeaderBg(txtWOrder) setHeaderBg(txtDElNote) setHeaderBg(txtCompany) // setHeaderBg(txtAddress) setHeaderBg(txtWeight) setHeaderBg(txtbutton1) setHeaderBg(txtbutton2) setHeaderBg(txttvdone) txtWOrder.text = "WOrder" txtDElNote.text = "DElNote" txtCompany.text = "Company" // txtAddress.text = "Address" txtWeight.text = "Weight" txtbutton1.text = "Delivered" txtbutton2.text = "Exception" txttvdone.text = "" } } else { val modal = Tripsheetlist[rowPos ] holder.itemView.apply { setContentBg(txtWOrder) setContentBg(txtDElNote) setContentBg(txtCompany) // setContentBg(txtAddress) setContentBg(txtWeight) setContentBg(txtbutton1) setContentBg(txtbutton2) setContentBg(txttvdone) txtWOrder.text = modal.WOrder.toString() txtDElNote.text = modal.DElNote.toString() txtCompany.text = modal.Company.toString() // txtAddress.text = modal.Address.toString() txtWeight.text = modal.Weight.toString() txtbutton1.text = modal.Button1.toString() txtbutton2.text = modal.Button2.toString() txttvdone.text = modal.tvdone.toString() } } holder.txttvdone.apply { setBackgroundResource(when (dataItem.state) { DataState.Unselected -> android.R.color.transparent DataState.Success -> R.color.green DataState.Failure -> R.color.orange }) text = when (dataItem.state) { DataState.Unselected -> "" DataState.Success -> "✓" DataState.Failure -> "x" //this is where I add code to export data through api maybe add it in the datastate set where it is success and Failure } } holder.apply { txtbutton1.setOnClickListener { Log.e("Clicked", "Successful delivery") //this is where I add code to export data through api dataItem.state = DataState.Success notifyDataSetChanged() } txtbutton2.setOnClickListener { Log.e("Clicked", "Exception on delivery") dataItem.state = DataState.Failure notifyDataSetChanged() } } } class RowViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){ val txttvdone:TextView = itemView.findViewById<TextView>(R.id.txttvdone) val txtbutton1:Button = itemView.findViewById<Button>(R.id.txtbutton1) val txtbutton2:Button = itemView.findViewById<Button>(R.id.txtbutton2) } class MyViewHolder(val view: View) : RecyclerView.ViewHolder(view) { var txtbutton1 = view.findViewById<Button>(R.id.txtbutton1) val txtbutton2:Button = itemView.findViewById<Button>(R.id.txtbutton2) var txttvdone = view.findViewById<TextView>(R.id.txttvdone) } private fun setHeaderBg(view: View) { view.setBackgroundResource(R.drawable.table_header_cell_bg) } private fun setContentBg(view: View) { view.setBackgroundResource(R.drawable.table_content_cell_bg) } } I have created something with a button just to test it out. But what happens is. The data only changes after clicking the load data button and then a button on my recycler view, which is not ideal. btnLoadData.setOnClickListener(View.OnClickListener { var x: Int = 2 for (i in 3..6) { //does not work this.Tripsheetlist[x].WOrder = 20022 this.Tripsheetlist[x].DElNote = 20022 this.Tripsheetlist[x].Company = "FNB" this.Tripsheetlist[x].Weight = 20 this.Tripsheetlist[x].Button1 = "No exceptions" this.Tripsheetlist[x].Button2 = "Exceptions" this.Tripsheetlist[x].tvdone = "" x++ } Any and all help is appreciated. Let me know if any additional information is needed. For my layouts. I have a activity main with my recycler view and then a table list item for my rows. Below is how my app looks.
There are two ways to approach this, add a setData method to RV , so your part of code looks like class TableViewAdapter(){ private var data : List<DataModel> = emptyList() fun setData( newData : List<..>){ data = newData notifyDataSetChanged() // and handle other events to update } } then you can update data on go use DiffUtil supported RV like ListAdapter or implement it yourself
Randomize question on Android Studio - Kotlin
I made a simple quiz on Android Studio which contains 8 questions. How to make the questions become random without duplicated. This app does not use a database. I'm new to programming so I don't know what to do about this Here's the code Kuis Activity private lateinit var kuis: TextView private lateinit var rg: RadioGroup private lateinit var choiceA: RadioButton private lateinit var choiceB: RadioButton private lateinit var choiceC: RadioButton private lateinit var choiceD: RadioButton private var number = 0 val question: Array<String> = arrayOf( "Mandau merupakan senjata tradisional yang berasal dari suku...", "Pakaian tradisional suku Madura bernama...", "Suku yang teridentifikasi memiliki 13 kerajaan adalah...", "Cheongsam merupakan pakaian tradisional dari...", "Lagu Jubata merupakan lagu yang berasal dari suku Dayak yang memiliki arti...", "Berikut ini merupakan kuliner khas Kalimantan Barat kecuali...", "'Takadang jantu barang dah latih'. Penggalan lirik tersebut berasal dari lagu...", "Rumah Adat Saoraja merupakan rumah adat yang berasal dari suku..." ) val option = arrayOf( "Jawa", "Dayak", "Melayu", "Bugis", "Batik", "Teluk Belanga", "King Baba", "Pesa'an", "Jawa", "Dayak", "Melayu", "Madura", "Tionghoa", "Dayak", "Melayu", "Bugis", "Tanah", "Tuhan", "Sungai", "Keselamatan", "Kwetiau", "Pengkang", "Rendang", "Chai Kwe", "Tanah Parenean", "Jubata", "Cik Cik Periuk", "Sungai Kapuas", "Dayak", "Tionghoa", "Melayu", "Bugis" ) val answer = arrayOf( "Dayak", "Pesa'an", "Melayu", "Tionghoa", "Tuhan", "Rendang", "Jubata", "Bugis" ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_kuis) supportActionBar?.title = "Kuis" kuis = findViewById(R.id.kuis) rg = findViewById(R.id.pilihan) choiceA = findViewById(R.id.pilihanA) choiceB = findViewById(R.id.pilihanB) choiceC = findViewById(R.id.pilihanC) ChoiceD = findViewById(R.id.pilihanD) kuis.setText(question[number]) choiceA.setText(option[0]) choiceB.setText(option[1]) choiceC.setText(option[2]) choiceD.setText(option[3]) rg.check(0) correct = 0 wrong = 0 } fun next(view: View) { if (choiceA.isChecked || choiceB.isChecked || choiceC.isChecked || choiceD.isChecked) { val userAnswer: RadioButton = findViewById(rg.checkedRadioButtonId) val takeUserAnswer: String = userAnswer.text.toString() rg.check(0) if (takeUserAnswer.equals(answer[number])) correct++ else wrong++ number++ if (number< 8) { kuis.setText(question[number]) choiceA.setText(option[(number * 4) + 0]) choiceB.setText(option[(number * 4) + 1]) choiceC.setText(option[(number * 4) + 2]) choiceD.setText(option[(number * 4) + 3]) } else { result = correct * 100 / 8 val intent = Intent(this, HasilKuis::class.java) startActivity(intent) } } else { Toast.makeText(this, "Belum Dijawab", Toast.LENGTH_SHORT).show() }
Inefficient way would be something like this: val soal = mutableListOf<String>(...) val indices = mutableSetOf<Int>() do { val randomIndex = Random.nextInt(soal.size) if (randomIndex !in indices) { // Update views with their respective data using the randomIndex, e.g. soal[randomIndex] indices.add(randomIndex) } } while (indices.size < 8) The efficient way would be to make your arrays MutableList<String> and modify their size along the way: val soal = mutableListOf<String>(...) var upperBound = soal.lastIndex do { val randomIndex = if (upperBound != 0) Random.nextInt(upperBound) else 0 // Update views with their respective data using the randomIndex, e.g. soal.removeAt(randomIndex) upperBound-- } while (soal.isNotEmpty())
Android with Kotlin recyclerView with checkboxes randomly checked after delete list item
apologies for my limited knowledge of programming and any sloppiness. I have a reyclerview with alarm objects that I can add and it creates them. When I add say 4 alarms, and delete three of them. The last alarms checkbox is checked by itself. I can not in anyway use the checkbox.setChecked() method for some reason. android studio is not recognizing it, if anyone could please let me know why that is. Also if you know of a solution to the auto check on the last alarm object please. package com.example.alarmclock import android.view.KeyEvent import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.Checkable import android.widget.EditText import android.widget.TextView import androidx.core.widget.doAfterTextChanged import androidx.core.widget.doBeforeTextChanged import androidx.recyclerview.widget.RecyclerView import java.security.Key class AlarmAdapter (private val alarmList: MutableList<Alarm>) : RecyclerView.Adapter<AlarmAdapter.ViewHolder>() { //start viewholder inner class ViewHolder(alarm: View) : RecyclerView.ViewHolder(alarm) { val alarmLabel = itemView.findViewById<EditText>(R.id.alarmLabel) val editTextTime = itemView.findViewById<EditText>(R.id.editTextTime) val textView1 = itemView.findViewById<TextView>(R.id.textView1) val deleteCheckBox = itemView.findViewById<Button>(R.id.deleteAlarmCheckBox) //val deleteButton = itemView.findViewById<Button>(R.id.deleteAlarmButton) //val addButton = itemView.findViewById<Button>(R.id.addAlarmButton) val mondayCheckBox = itemView.findViewById<Button>(R.id.mondayCheckBox) val tuesdayCheckBox = itemView.findViewById<Button>(R.id.tuesdayCheckBox) val wednesdayCheckBox = itemView.findViewById<Button>(R.id.wednesdayCheckBox) val thursdayCheckBox = itemView.findViewById<Button>(R.id.thursdayCheckBox) val fridayCheckBox = itemView.findViewById<Button>(R.id.fridayCheckBox) val saturdayCheckBox = itemView.findViewById<Button>(R.id.saturdayCheckBox) val sundayCheckBox = itemView.findViewById<Button>(R.id.sundayCheckBox) val amCheckBox = itemView.findViewById<Button>(R.id.amCheckBox) val pmCheckBox = itemView.findViewById<Button>(R.id.pmCheckBox) }//end viewholder fun addAlarm (alarm: Alarm) { alarmList.add(alarm) notifyItemInserted(alarmList.size - 1) } fun returnAlarmList (): MutableList<Alarm> { return alarmList } fun removeAlarms() { alarmList.removeAll { alarm -> alarm.deleteCheck == true } //notifyDataSetChanged() } fun deleteAlarm (deletedAlarmList: List<Int> ) { val deletedListIterator = deletedAlarmList.iterator() val alarmListIterator = alarmList.iterator() while (deletedListIterator.hasNext()){ while (alarmListIterator.hasNext()){ if (deletedListIterator.next() == alarmListIterator.next().alarmId){ alarmList.remove(alarmListIterator.next()) } } } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val context = parent.context val inflater = LayoutInflater.from(context) val alarmView = inflater.inflate(R.layout.alarms, parent, false) return ViewHolder(alarmView) } override fun getItemCount(): Int { return alarmList.size } override fun onBindViewHolder(holder: AlarmAdapter.ViewHolder, position: Int) { val alarm: Alarm = alarmList[position] val alarmLabel = holder.alarmLabel var textView1 = holder.textView1 var editTextTime = holder.editTextTime var mondayCheckBox = holder.mondayCheckBox var tuesdayCheckBox = holder.tuesdayCheckBox var wednesdayCheckBox = holder.wednesdayCheckBox var thursdayCheckBox = holder.thursdayCheckBox var fridayCheckBox = holder.fridayCheckBox var saturdayCheckBox = holder.saturdayCheckBox var sundayCheckBox = holder.sundayCheckBox var amCheckBox = holder.amCheckBox var pmCheckBox = holder.pmCheckBox var deleteAlarmCheckBox = holder.deleteCheckBox var lastCharacter = "" var secondLastCharacter = "" deleteAlarmCheckBox.setOnClickListener { alarm.deleteCheck = !alarm.deleteCheck } alarmLabel.doAfterTextChanged { alarm.alarmLabel = alarmLabel.text.toString() textView1.text = alarm.alarmLabel } editTextTime.doAfterTextChanged { //lastCharacter = editTextTime.text.get(editTextTime.text.length-1).toString() textView1.text = lastCharacter if (editTextTime.text.length == 2 && secondLastCharacter != ":"){ //if (lastCharacter != ":") { editTextTime.setText(editTextTime.text.toString().plus(":")) editTextTime.setSelection(editTextTime.text.length) //} } editTextTime.doBeforeTextChanged { _, _, _, _ -> if (editTextTime.length() != 0) { secondLastCharacter = editTextTime.text.get(editTextTime.text.length - 1).toString() } } if (editTextTime.text.length == 5 ){ alarm.hour = editTextTime.text.get(0).toString().plus(editTextTime.text.get(1).toString()) if (alarm.hour.toInt() < 10) alarm.hour = "0".plus(alarm.hour) /////// var inputedTimeList = editTextTime.text.toList() val timeIterator = inputedTimeList.iterator() } } mondayCheckBox.setOnClickListener { alarm.monday = !alarm.monday textView1.text = alarm.monday.toString() } tuesdayCheckBox.setOnClickListener { alarm.tuesday = !alarm.tuesday } wednesdayCheckBox.setOnClickListener { alarm.wednesday = !alarm.wednesday } thursdayCheckBox.setOnClickListener { alarm.thursday = !alarm.thursday } fridayCheckBox.setOnClickListener { alarm.friday = !alarm.friday } saturdayCheckBox.setOnClickListener { alarm.saturday = !alarm.saturday } sundayCheckBox.setOnClickListener { alarm.sunday = !alarm.sunday } amCheckBox.setOnClickListener { alarm.amPm = !alarm.amPm } } }
The answer is quite simple, RecyclerView items are reused, so be sure that you set the all the values onBindViewHolder, because after your item is deleted, the actual view is not, so previously set values might be preset although they are not correct according to your data. The easiest way would be to have isChecked Boolean value store in the Alarm object, onBindViewHolder always set the isChecked param on the Checkbox according to the value returned from the Alarm and when you change the isChecked inside the Checkbox listener - make sure you also update the value inside the Alarm object. Another solution would be calling notifyDatasetChanged() on the RecyclerView, but it's definitely not the best solution especially if you have dynamic row deletion (and possibly a neat animation). P.S. consider using viewBinding in your project, it will save you time writing all that ugly findViewById code :)))
Android Animated Carousel TextView within RecyclerView width wider than screen text gets clipped off. Even when animated into view
I am building a stock ticker type carousel that has market prices running along the screen as shown. The 'CRC' Ticker has only the partial view showing, it clips off at the edge of the parent which is the width of the device even when it is animated into view. I want it to have a width large enough hold all the children that goes past the device width. Here if the Carousel layout xml: <?xml version="1.0" encoding="utf-8"?> <com.android.forexwatch.views.timepanel.CarouselView xmlns:android="http://schemas.android.com/apk/res/android" android:id="#+id/carouselLinear" android:layout_width="match_parent" android:layout_height="30dp" android:orientation="horizontal" android:singleLine="true" android:animateLayoutChanges="true" /> Here is the class: package com.android.forexwatch.views.timepanel import android.content.Context import android.util.AttributeSet import android.view.ContextThemeWrapper import android.view.LayoutInflater import android.widget.RelativeLayout import androidx.appcompat.widget.LinearLayoutCompat import com.android.forexwatch.model.Index import com.android.forexwatch.R import com.android.forexwatch.model.CityInfoDetailed import com.github.ybq.android.spinkit.SpinKitView class CarouselView(context: Context, attrs: AttributeSet): LinearLayoutCompat(context, attrs) { companion object { private const val IndexWidth = 600F } private var contextThemeWrapper: ContextThemeWrapper? = null init { contextThemeWrapper = ContextThemeWrapper(context.applicationContext, R.style.Theme_ForexWatch) } fun setupView ( cityInfo: CityInfoDetailed?, isMirror: Boolean = false) { createPriceTickerViews(cityInfo, isMirror) } private fun createPriceTickerViews(cityInfo: CityInfoDetailed?, isMirror: Boolean = false) { destroy() removeAllViews() var calculatedWidth = 0 cityInfo?.indexes?.forEachIndexed { index, element -> if (isMirror) index.plus(cityInfo?.indexes.count()) val loader: SpinKitView = LayoutInflater.from(contextThemeWrapper).inflate(R.layout.preloader, null) as SpinKitView val priceTicker: PriceTicker = LayoutInflater.from(contextThemeWrapper).inflate(R.layout.price_ticker, null) as PriceTicker addView(priceTicker) addView(loader) // priceTicker.x = IndexWidth * index calculatedWidth.plus(IndexWidth) priceTicker.initialize(element, cityInfo, loader) } layoutParams.width = calculatedWidth } private fun destroy() { for (idx in 0 .. this.childCount) { val view = getChildAt(idx) if (view is PriceTicker) { view.destroy() } } } } Here is the parent class: package com.android.forexwatch.views.timepanel import android.animation.ValueAnimator import android.graphics.Color import android.view.View import android.view.ViewGroup import android.view.animation.LinearInterpolator import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.android.forexwatch.R import com.android.forexwatch.adapters.TimePanelRecyclerViewAdapter import com.android.forexwatch.events.TimeEvent import com.android.forexwatch.model.CityInfoDetailed import com.android.forexwatch.model.TimeObject import com.android.forexwatch.utils.TimeKeeper import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe class TimePanelView(view: View, container: ViewGroup, timePanelAdapter: TimePanelRecyclerViewAdapter) : RecyclerView.ViewHolder(view) { companion object { private const val OffsetTime: Long = 15 * 60 private const val FrameRate: Long = 32 } private var fxTime: TextView? = null private var stockTime: TextView? = null private var city: TextView? = null private var currentTime: TextView? = null private var fxTimeLabel: TextView? = null private var stockTimeLabel: TextView? = null private var carouselView: CarouselView? = null private var carouselViewMirror: CarouselView? = null private var parentContainer: ViewGroup? = null private var adapter: TimePanelRecyclerViewAdapter? = null private var cityInfo: CityInfoDetailed? = null private var view: View? = null init { adapter = timePanelAdapter this.view = view this.parentContainer = container EventBus.getDefault().register(this) } fun setupView(cityInfo: CityInfoDetailed?) { this.cityInfo = cityInfo city = view?.findViewById(R.id.city) stockTime = view?.findViewById(R.id.stockTime) fxTime = view?.findViewById(R.id.fxTime) fxTimeLabel = view?.findViewById(R.id.fxTimeLabel) stockTimeLabel = view?.findViewById(R.id.stockTimeLabel) currentTime = view?.findViewById(R.id.currentTime) carouselView = view?.findViewById(R.id.carouselLinear) carouselViewMirror = view?.findViewById(R.id.carouselLinearMirror) city?.text = cityInfo?.cityName createCarousel() } #Subscribe fun update(event: TimeEvent.Interval?) { updateCurrentTime() updateFxTime() updateStockTime() } private fun createCarousel() { carouselView?.setupView(cityInfo) carouselViewMirror?.setupView(cityInfo, true) carouselView?.bringToFront() carouselViewMirror?.bringToFront() animateCarousel() } private fun updateCurrentTime() { val timezone: String? = cityInfo?.timeZone currentTime?.text = TimeKeeper.getCurrentTimeWithTimezone(timezone, "EEE' 'HH:mm:ss") } private fun updateFxTime() { updateTime(fxTime, fxTimeLabel, cityInfo?.forexOpenTimes, cityInfo?.forexCloseTimes, cityInfo?.timeZone, "FX", Companion.OffsetTime * 8) } private fun updateStockTime() { updateTime(stockTime, stockTimeLabel, cityInfo?.stockOpenTime, cityInfo?.stockCloseTime, cityInfo?.timeZone, cityInfo?.stockExchangeName, Companion.OffsetTime) } private fun updateTime(timeView: TextView?, timeLabel: TextView?, open: TimeObject?, close: TimeObject?, timezone: String?, type: String?, timeOffset: Long) { if (TimeKeeper.isMarketOpen(open, close, timezone)) { timeView?.text = TimeKeeper.getTimeDifference(close, close, timezone, true) displayMarketColors(timeView, timeOffset, close, timezone, Color.GREEN, true) timeLabel?.text = "To " + type + " Close" } else { timeView?.text = TimeKeeper.getTimeDifference(open, close, timezone, false) displayMarketColors(timeView, timeOffset, open, timezone, Color.RED, false) timeLabel?.text = "To " + type + " Open" } } private fun displayMarketColors(timeView: TextView?, timeOffset: Long, time: TimeObject?, timezone: String?, outRangeColor: Int, isMarketOpen: Boolean?) { val color = if (TimeKeeper.isTimeWithinRange(timeOffset, time, timezone, isMarketOpen)) Color.parseColor("#FF7F00") else outRangeColor timeView?.setTextColor(color) } private fun animateCarousel() { if (cityInfo?.indexes?.count() == 1) { return } // carouselView?.x = carouselView?.x?.minus(3.0F)!! /* CoroutineScope(Dispatchers.Main).launch { delay(FrameRate) animateCarousel() }*/ val animator = ValueAnimator.ofFloat(0.0f, 1.0f) animator.repeatCount = ValueAnimator.INFINITE animator.interpolator = LinearInterpolator() animator.duration = 18000L animator.addUpdateListener { animation -> val progress = animation.animatedValue as Float val width: Int? = carouselView?.width val translationX = -width?.times(progress)!! carouselView?.translationX = translationX!! carouselViewMirror?.translationX = translationX!! + width!! } animator.start() } } The PriceTicker layout which extends AppCompatTextView <com.android.forexwatch.views.timepanel.PriceTicker xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" class="com.android.forexwatch.views.timepanel.PriceTicker" android:layout_width="240dp" android:layout_height="match_parent" android:textAlignment="center" android:textSize="13sp" android:singleLine="true" android:background="#drawable/rectangle_shape" app:layout_constraintBottom_toBottomOf="parent" />
I found the solution by invalidating and requestingLayout on the priceTicker TextView and the container. Also changed the width of the container and priceTicker to the desired width. calculatedWidth = calculatedWidth.plus(IndexWidth).toInt() priceTicker.initialize(index, cityInfo, loader) priceTicker.width = IndexWidth.toInt() resetLayout(priceTicker) } layoutParams.width = (calculatedWidth) resetLayout(thisContainer) } } private fun destroy() { for (idx in 0 .. this.childCount) { val view = getChildAt(idx) if (view is PriceTicker) { view.destroy() } } } private fun resetLayout(view: View?) { view?.invalidate() view?.requestLayout() }
Android PreferenceFragmentCompat title blank space
I don't know why using this Fragment can make the problem , it seems that isIconSpaceReserved = false is useful for not preferenceCagory class TFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { val context = preferenceManager.context val screen = preferenceManager.createPreferenceScreen(context) val category1 = PreferenceCategory(context) category1.title = "button" category1.summary = "what is the problem" category1.key = "bbb" val swithButton = SwitchPreferenceCompat(context) swithButton.title = "button" swithButton.summary = "summary" swithButton.key = "sss" swithButton.isIconSpaceReserved = false val swithButton2 = EditTextPreference(context) swithButton2.title = "edit" val swithButton3 = SeekBarPreference(context) swithButton3.title = "seekbar" swithButton3.value = 1 screen.addPreference(category1) category1.addPreference(swithButton) val category2 = PreferenceCategory(context) category2.title = "category2" screen.addPreference(category2) category2.addPreference(swithButton2) category2.addPreference(swithButton3) preferenceScreen = screen } style is normal, I try so many ways but it's useless.
now, I tried the 'androidx.preference:preference:1.1.0-alpha01' , so lucky, It fixed the bug that the isIconSpaceReserved was not supported for PreferenceCategory. override fun setPreferenceScreen(preferenceScreen: PreferenceScreen?) { super.setPreferenceScreen(preferenceScreen) if (preferenceScreen != null) { val count = preferenceScreen.preferenceCount for (i in 0 until count) { if (preferenceScreen.getPreference(i) is PreferenceCategory) { val category = preferenceScreen.getPreference(i) as PreferenceCategory val childCount = category.preferenceCount for (j in 0 until childCount) { category.getPreference(j).isIconSpaceReserved = false } } preferenceScreen.getPreference(i).isIconSpaceReserved = false } } }