How to set a list/array to a TextView - android

I have a mutable list that changes each time the generate() function is called. What I'm trying to do is convert it to a string and set it to a TextView. The way I set the TextView below works for Integers but not for lists. It just does not display the contents of the list and I have no idea why it won't work. Instead the TextView2 does this: Genereated Numbers: []
val text = findViewById<TextView>(R.id.textView)
val text2 = findViewById<TextView>(R.id.textView2)
var possibleInputs = mutableListOf(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
fun generate() {
var num = (0..20).shuffled().last()
when {
possibleInputs.size == 0 -> text.text = "Done"
num in possibleInputs -> {
text.text = "$num"
text2.text = "Generated Numbers: $possibleInputs"
possibleInputs.remove(num)
}
else -> generate()
}
}

This is the code I used to fix it
for (i in 0 until possibleInputs.size) {
text2.append(possibleInputs[i].toString())
}

Related

Formating a string from right to left for currency values

I'm working on creating a way to input an amount and format it from left to right with placeholder zeros.
For example, pressing 1 and 2 would show $0.12 pressing 3 would give $1.23. Pressing backspace would give $0.12.
Instead, I am getting $1,0002.00
binding.keypad.btnBackspace.setOnClickListener {
val text = binding.tvTotalValue.text.toString()
if(text.isNotEmpty()) {
binding.tvTotalValue.text = text.drop(1)
}
binding.tvTotalValue.text = ""
}
binding.keypad.onNumberSelected = {
processNewAmount(it.toString())
}
private fun processNewAmount(newValue: String) {
val text = binding.tvTotalValue.text.toString().plus(newValue)
val result = text.replace("[^0-9]".toRegex(), "") // remove any characters
val amount = result.toDouble()
binding.tvTotalValue.text = NumberFormat.getCurrencyInstance().format(amount)
}
What am I doing wrong?
Is there a better way to do this?
I advise keeping a property that stores the entered value without formatting. Each time a number is added, you can add it to this entered number and then format it for the screen. That will be a lot simpler than trying to move/remove existing symbols around in the String.
private var enteredNumber = ""
//...
binding.keypad.btnBackspace.setOnClickListener {
enteredNumber = enteredNumber.dropLast(1)
refreshTotal()
}
binding.keypad.onNumberSelected = {
if(!(it == 0 && enteredNumber == "0")) { // avoid multiple zeros or backspace will act unexpectedly
enteredNumber += it.toString()
refreshTotal()
}
}
//...
private fun refreshTotal() {
val amount = enteredNumber.toDouble() / 100.0
binding.tvTotalValue.text =
NumberFormat.getCurrencyInstance().format(amount)
}

Print out 6 distinct numbers in Kotlin

// Create new 6 Pot
val list = mutableListOf<Int>()
val pot = listOf<Pot>(Pot(50), Pot(50), Pot(50), Pot(50), Pot(50), Pot(50))
val linearLayout: LinearLayout = findViewById(R.id.text)
linearLayout.removeAllViews()
// random 6 number from 1 - 50 without duplicate
// Create textview to print out roll result
pot.forEach {
val d = it
val rollResult = d.roll()
list.add(rollResult)
val textView = TextView(this)
textView.append(this.toString())
val param = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
param.marginStart = 10
textView.layoutParams = param
textView.text = rollResult.toString()
linearLayout.addView(textView)
}
I have a code like this, after add rollResult to a list like a temp paper, what should i do to compare next result to previous result which is in the list, if it already present then do another roll, from start to end. Thanks
You can use distinct(),
Ref : https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/distinct.html
Example
var list = listOf(1,2,4,5,1,6,8,2,4,3,3,5)
list = list.distinct();
println(list)
First loop for generating roll results
pot.forEach {
val d = it
val rollResult = d.roll()
list.add(rollResult)
}
Second Loop for adding dynamic views
list = list.distinct();
list.forEach {
// Add Views etc
}
Modify as per your needs.
Check whether the element is present in the whole list or not try below code :
if(list.contains(element)){ // do rollout again}

How to update recyclerview element and retrieve sum all updated elements

Updating value of recyclerview but unable to update corresponding data in model class
Model classes
#Parcelize
class GetStockListData : ArrayList<GetStockListDataItem>(), Parcelable
#Parcelize
data class GetStockListDataItem(
var Qty:#RawValue Double,
var selectedQty: Double
): Parcelable
able to change recyclerview element using alertbox as follows
private fun showAlertDialog(stockListData: GetStockListData, position: Int) {
val layoutInflater = LayoutInflater.from(context)
val customView =
layoutInflater.inflate(R.layout.change_qty_dialog, null)
val myBox: android.app.AlertDialog.Builder = android.app.AlertDialog.Builder(context)
myBox.setView(customView)
val dialog = myBox.create()
dialog.show()
val etQuantity = customView.findViewById<AppCompatEditText>(R.id.et_quantity)
if (stockListData[position].Qty < args.getListDetailsByRNumberModelItem.ReqQty) {
val df = DecimalFormat("#.##")
df.roundingMode = RoundingMode.CEILING
etQuantity.setText(df.format(stockListData[position].Qty).toString())
} else
etQuantity.setText(args.getListDetailsByRNumberModelItem.ReqQty.toString())
etQuantity.setSelection(etQuantity.text.toString().length)
etQuantity.requestFocus()
requireContext().showKeyboard()
customView.findViewById<Button>(R.id.btnDone).setOnClickListener {
if(!etQuantity.text.isNullOrEmpty()) {
val qtyStr = etQuantity.text.toString().trim()
var qtyDouble = qtyStr.toDouble()
stockListData[position].selectedQty = qtyDouble
adapter.notifyDataSetChanged()
dialog.dismiss()
}
}
}
for (i in 0 until stockListData.size){
sum += stockListData[i].selectedQty
}
here if user edit Recyclerview list item multiple times, each value added to list. Finally if i try to retrieve sum of all recyclerview elements getting wrong value because in model class values are added when i try to replace element.
Instead of passing whole list as parameter to showAlertDialog() method, you could just pass single item which has to be updated. And one more thing, you should not call adapter.notifyDataSetChanged() for single item updation, rather call adapter.notifyItemChanged(position). Look at below code, I am getting correct sum :
private fun showRecipeMeasureDialog(recipeItem: RecipeItem?,position: Int){
val dialogView = LayoutInflater.from(context).inflate(R.layout.add_recipe_measure_dialog, null)
val dialog = AlertDialog.Builder(context, R.style.RoundedCornersDialog).setView(dialogView).show()
dialog.setCancelable(false)
val displayRectangle = Rect()
val window = activity?.window
window?.decorView?.getWindowVisibleDisplayFrame(displayRectangle)
dialog.window?.setLayout(
(displayRectangle.width() * 0.5f).toInt(),
dialog.window!!.attributes.height
)
context?.resources?.let {
dialogView.findViewById<TextView>(R.id.recipe_measure_title).text = java.lang.String.format(it.getString(R.string.addRecipeMeasure), unitsArray[currentMeasurementUnits - 1])
}
val doneBtn = dialogView.findViewById<ImageButton>(R.id.recipe_measure_done_btn)
val closeBtn = dialogView.findViewById<ImageButton>(R.id.close_btn_add_recipe)
val conversionEditText = dialogView.findViewById<ClearFocusEditText>(R.id.recipe_conversion_tie)
doneBtn.isEnabled = false
if (recipeItem != null ){
conversionEditText.setText("${recipeItem.conversionRatio}")
}
closeBtn.setOnClickListener {
context?.hideKeyboard(it)
dialog.dismiss() }
doneBtn.setOnClickListener {
context?.hideKeyboard(it)
val conversionRatio = conversionEditText.text.toString().toFloat()
if (recipeItem != null){
recipeItem.conversionRatio = conversionRatio
recipeItemList[position] = recipeItem
recipeAdapter.notifyItemChanged(position)
}else{
recipeItemList.add(0,RecipeItem(0,0,conversionRatio,0)) // Use your data class in place of RecipeItem
recipeAdapter.notifyItemInserted(0) // new Item is added to index zero, so adapter has to be updated at index zero
}
// calculating sum
val sum = recipeItemList.map { it.conversionRatio }.sum()
Log.d("tisha==>>","Conversion ratio sum = $sum")
dialog.cancel()
}
}

Dynamic array of views in Kotlin

I am trying to create dynamic TextView by creating an array of TextViews but getting error :
java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
My Code:
var txtViews = arrayOfNulls<TextView>(3)
for (i in txtViews.indices) {
txtViews = arrayOfNulls(i)
txtViews[i]?.textSize = 24.0F
txtViews[i]?.text = "Hello"
txtViews[i]?.setTextColor(ContextCompat.getColor(this,
R.color.colorAccent))
layout.addView(txtViews[i])
}
You never initialized those null references inside your array:
This should work for what you are trying to achieve:
val txtViews = arrayOfNulls<TextView>(3)
for (i in txtViews.indices) {
txtViews[i] = TextView(context).apply {
textSize = 24.0F
text = "Hello"
setTextColor(
ContextCompat.getColor(context,
R.color.colorAccent))
}
layout.addView(txtViews[i])
}
There was no need to create arrayOfNulls
I did this way:
for (i in size) {
val txtView = TextView(this).apply {
textSize = 24.0F
text = Html.fromHtml("&#8226")
setTextColor(
ContextCompat.getColor(
context,
R.color.colorAccent
)
)
}
layout.addView(txtView)
}

Android implement text completion on swipe

How can I implement text completion,Like Gmail's smart compose?
I've an edit text where the user enters server address and I want to detect when they start typing the domain suffix and suggest completion.
Thanks.
First you need an algorithm to get suggestion from a given dictionary.
I've created a simple class named SuggestionManager to get suggestion from a given dictionary for a string input. Instead of returning the full match, it'll only return the remaining part of the given input. Below given a simple unit test along with full source code of the class. You can also go here to run the test online.
SuggestionManager.kt
class SuggestionManager(private val dictionary: Array<String>) {
companion object {
private val WORD_SPLIT_REGEX = Regex("[^A-Za-z0-9'\\-]")
/**
* To get reversed list
*/
private fun getReversedList(list: List<String>): MutableSet<String> {
val reversed = mutableSetOf<String>()
for (item in list.withIndex()) {
if (item.index != 0) {
val rev = list.subList(list.size - item.index, list.size).joinToString(" ")
reversed.add(rev)
}
}
// finally, add the full string
reversed.add(list.joinToString(" "))
return reversed
}
}
fun getSuggestionFor(_text: String?): String? {
var text = _text
// empty text
if (text.isNullOrBlank()) {
return null
}
// Getting last line only
if (text.contains("\n")) {
text = text.split("\n").last()
if (text.trim().isEmpty()) {
return null
}
}
// Splitting words by space
val words = text.split(WORD_SPLIT_REGEX).filter { it.isNotBlank() }
// Getting last word
val lastWord = if (text.endsWith(" ")) "${words.last()} " else words.last()
// Matching if last word exist in any dictionary
val suggestions = mutableSetOf<String>()
for (dicItem in dictionary) {
if (dicItem.contains(lastWord, true)) {
// Storing founded matches
suggestions.add(dicItem)
}
}
// Reverse ordering split-ed words
val pyramidWords = getReversedList(words)
val matchList = mutableListOf<String>()
for (pw in pyramidWords) {
for (sug in suggestions) {
// Storing suggestions starts with reversed word
if (sug.startsWith(pw, true)) {
matchList.add("$pw:$sug")
}
}
}
// Checking if second level match is not empty
if (matchList.isNotEmpty()) {
// Ordering by matched reversed word - (largest key first)
matchList.sortBy { -it.split(":")[0].length }
// Looping through in ascending order
for (m in matchList) {
val match = m.split(":")
val selPw: String = match[0]
var selSug: String = match.subList(1, match.size).joinToString(":")
// trimming to
selSug = selSug.replace(selPw, "", true)
if (text.endsWith(" ")) {
selSug = selSug.trim()
}
return selSug
}
}
return null
}
}
Unit Test
class SuggestionManagerUrlTest {
private val suggestionManager by lazy {
val dictionary = arrayOf(
"google.com",
"facebook.com",
"gmail.com",
"yahoo.com",
"192.168.354.45"
)
SuggestionManager(dictionary)
}
#Test
fun test() {
// null of empty and null input
assertNull(suggestionManager.getSuggestionFor(null))
assertNull(suggestionManager.getSuggestionFor(""))
// matching
assertEquals("ogle.com", suggestionManager.getSuggestionFor("go"))
assertEquals("book.com", suggestionManager.getSuggestionFor("face"))
assertEquals(".168.354.45", suggestionManager.getSuggestionFor("192"))
// no match
assertNull(suggestionManager.getSuggestionFor("somesite"))
}
}
Then, you'll have to set text in EditText with two colors. One for input and other for the suggestion. You may use the Html.fromHtml method to do this.
val text = "<font color=#cc0029>$input</font> <font color=#ffcc00>$suggestion</font>";
yourEditText.setText(Html.fromHtml(text));
Combining these two aspects, you can create a custom EditText.

Categories

Resources