Programatically make an imageView visible/invisible using a variable - android

I have a Kotlin function, that works as expected when an imageView is explicitly called. However when a variable 'cellName' is used the code will not compile.
My objective here is to programatically generate the imageView name and then set/unset its visibility. Could someone please tell me where I am going wrong.
TIA
fun game(view: View) {
var col = 1
var row = 0
var cellName = ""
object : CountDownTimer(10000, 1000){
override fun onFinish() {
Toast.makeText(applicationContext, "Time's Up", Toast.LENGTH_LONG).show()
textView9.text = "Time: 0"
}
override fun onTick(p0: Long) {
textView9.text = "Time: "+ p0 /1000
// Hide current position
cellName = "imageView"+row+col
imageView01.setVisibility(View.INVISIBLE)
// Get next random position
// Show new Position
}
}.start()
}
So:
imageView01.setVisibility(View.INVISIBLE) --> works
cellName.setVisibility(View.INVISIBLE) -- does not compile

You can generate a view id (aka an R.id constant) by using Resources.getIdentifier().
A sample for your code (assuming you're running inside an Activity) might be:
int row = 0;
int col = 1;
String name = "imageView" + row + col;
int id = getResources().getIdentifier(name, "id", getPackageName());
ImageView imageView = findViewById(id);
imageView.setVisibility(View.INVISIBLE);
Sorry that this is in Java, not Kotlin. Hopefully you can adapt it.

Your best bet might be to just put all the ImageViews in question into a map where the value you have for "cellName" is the key. Then just retrieve each ImageView from the map.

Related

Find button by ID in Kotlin

I have a user interface with multiple buttons. They have the IDs "button1", "button2", ...
I want to set an OnClickListener for all of them in a for loop. I dont want to type a line like button1.setOnClickListener for every button.
I have found one solution that works in java here: Android: Using findViewById() with a string / in a loop
And I tried to adapt it in Kotlin.
var buttons = ArrayList<Button>()
for (i in 1..7) {
var idString = "Button%i"
var buttonID = getResources().getIdentifier(idString, "id", packageName)
buttons.add( findViewWithTag(buttonID))
buttons[i].setOnClickListener(buttonclicked)
}
This throws an "Unresolved Reference" error. How can I access all buttons without typing a line for each of them?
Thanks in advance to all of you.
You call findViewWithTag() instead of findViewById() in your code.
Also you are not doing string interpolation correctly by var idString = "Button%i".
Change to this:
val buttons = ArrayList<Button>()
for (i in 1..7) {
val idString = "Button$i"
val buttonID = resources.getIdentifier(idString, "id", packageName)
buttons.add(findViewById(buttonID))
buttons[i].setOnClickListener(buttonclicked)
}

How to detect line breaks in TextView

In my Android App I've created 8 TextViews stacked on top of each other. Now I want to load in some plain text into those TextView-Lines. At the moment my Strings have a ";" as delimiter to indicate a line break, however it would be much more convenient if I would detect a linebreak automatically instead of using the hardcoded semicolon approach.
This is my String at the moment:
myString = "" +
"This seems to be some sort of spaceship,;" +
"the designs on the walls appear to be of;" +
"earth origin. It looks very clean here.;"
And in my other class I load in this string into the 8 TextViews, which I've loaded into an ArrayList, using the ";" as a delimiter.
public fun fillLines(myString: String) {
// How To Make Line Breaks Automatic??
for(i: Int in str until myString.split(";").size) {
if(i > textViewArray.size - 1) {
break
}
textViewArray[i].text = myString.split(";")[i]
textViewArray[i].alpha = 1.0f
}
}
Is there any way I can get the same result as shown above but without hardcoding the delimiter as ";" but instead somehow automatically detect the line break which would occur inside the TextView and then use this as a delimiter to advance through all 8 TextView "Lines".
The reason I need 8 TextViews Stacked On top of each other as individual "text lines" is because of an animation technique I want to use.
Line-breaking gets fairly complicated, so my recommendation would be that you allow a TextView to perform the measuring and layout to determine the line breaks. You could have an invisible TextView with the same style as your other views, and attach it to the layout so that it has the same width as your individual TextView instances. From there, add a layout change listener, and you can then retrieve the individual lines from the TextView Layout:
myTextView.text = // your text string here
myTextView.addOnLayoutChangeListener { view, _, _, _, _, _, _, _, _ ->
(view as? TextView)?.layout?.let { layout ->
// Here you'll have the individual broken lines:
val lines = (0 until layout.lineCount).map {
layout.text.subSequence(layout.getLineStart(it), layout.getLineVisibleEnd(it)
}
}
}
That said, this comes with the caveat that you'll lose out on hyphenation provided by the TextView, so you may wish to disable hyphenation entirely in your case.
You could fill text view with html. Below example.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
tvDocument.setText(Html.fromHtml(bodyData,Html.FROM_HTML_MODE_LEGACY));
} else {
tvDocument.setText(Html.fromHtml(bodyData));
}
If your delimiter ; it is possible call method replaceAll(";", "<br>");
Ok I got it working now:
First you must add these properties for the textviews:
android:singleLine="true"
android:ellipsize="none"
Then you can do this:
public fun fillStorylines() {
val linecap = 46
var finalLine: String
var restChars = ""
val index = 9999
val text1: String = "" +
"This seems to be some sort of spaceship, " +
"the designs on the walls appear to be of " +
"earth origin. It looks very clean here. "
for(j: Int in 0..index) {
try {
finalLine = ""
val lines: List<String> = (restChars + text1.chunked(linecap)[j]).split(" ")
for (i: Int in 0 until lines.size - 1) {
finalLine += lines[i] + " "
}
textViewArray[j].text = finalLine
textViewArray[j].alpha = 1.0f
restChars = lines[lines.size - 1]
} catch (ex: Exception) {
break
}
}
}
If anyone knows a more elegant way to solve this please go ahead, your feedback is appreciated :)

How to set the text of a Button using getResources() in Kotlin?

I'm trying to identify a button using getResources() and getIdentifier(), then set the text for it. The below code shows how I thought it should work (simply setting the ID and setting the text for the object).
while (c < 65) {
val resID = getResources().getIdentifier("S1", "id", getPackageName())
resID.text = ""
}
Instead I get an error, with ".text" showing red. How should I go about setting this up to run how I expected.
resID is the integer id of a Button "named" S1.
Use it to find the Button:
val resID = resources.getIdentifier("S1", "id", getPackageName())
val button = findViewById<Button>(resID)
button.text = ""
based on Docs getIdentifier returns Int , so you need findViewById and use the getIdentifier result in order to use the object
Kotlin Extensions do not work if the referenced int is not coming from R.id.
Button is a view, then you can access to it by using
findViewById<Button>(buttonId)
If you want to retrieve id from resources, just getResources().getIdentifier("S1", "id", getPackageName())
In conclusion, you see how this is going to be:
val buttonId = getResources().getIdentifier("S1", "id", getPackageName())
val button = findViewById<Button>(buttonId)
button.setText("")

Get the text of a dynamically created textfield in android studio (Kotlin)

So I'm trying to figure out how I would get the text from a dynamically created EditText field.
This is the code for the dynamic Text fields
private fun AddToDoItem() {
val EditText = EditText(this)
EditText.gravity = Gravity.TOP
EditText.gravity = Gravity.CENTER
EditText.tag = "ExtraField" + i
LinearLayout?.addView(EditText)
i++
}
And this is the code where I want to get the Textfields text
Finish.setOnClickListener {
var x = 0
val userId = mAuth.currentUser!!.uid
val mcDatabase = FirebaseDatabase.getInstance().getReference()
mcDatabase.child("Users").child(userId).child(ToDoName.text.toString()).push()
while (x < i) {
val currentUserDb = mDatabaseReference!!.child(userId).child(ToDoName.text.toString())
currentUserDb.child(i.toString()).setValue("ExtraField" + x.text) //HERE IS WHERE I WANT TO SET THE TEXT
x++
Toast.makeText(this, "Finished.", Toast.LENGTH_LONG).show()
}
}
Where its commented like "//HERE IS WHERE I WANT TO SET THE TEXT" is where I want the .text string.
(It's in the while loop)
There are two ways to handle this:
You are adding the EditText's to a LinearLayout therefore you can iterate over its children - as described here and therefore replacing the while loop.
The second way would be to add the EditText's to a List<EditText> and iterate over it, replacing the while loop.
The first solution would probably be cleaner, but both of them work in a very similar fashion.
Hope this helps you!

How to check whether the jigsaw puzzle is completed or not?

i am preparing one small game like jigsaw , for that i am using 9 imageview's with 9 different images in the layout. set the images to imageview at the time of starting those are actual images, after shuffle user will do sliding the images to complete puzzle, i want to check the modified image with actual image's, weather it's equal or not if those are equal popup a message, like gameover.
i tried like this
1.by using AND operator between the images(Drawables) but unlucky.
2.Using setLevel() for the images, compare those setLevel values with getLevel values for images after sliding still Unlucky.. here the problem is if i click on imageview one time getLevel() gives correct value, if i click more than once it gives zero value. Why it happens like this..
Please help me if you find any mistake in my code, otherwise guide me with good technique..
Xml code like this
<RelativeLayout
//9 imageview's
in jave code like this
if user will click on imageview it will swap the image's
img_View11.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(img_View21.getDrawable() == default_img ||
img_View12.getDrawable() == default_img) {
System.out.println("yes");
++click;
Noof_moves.setText("Moves: " +click);
ImageView iv = (ImageView)v;
d11 = iv.getDrawable();
prev_img = prev_imgView.getDrawable();
la11 = d11.getLevel();
System.out.println("d11 value is " +la11);
prev_imgView.setImageDrawable(d11);
img_View11.setImageDrawable(prev_img);
prev_imgView = img_View11;
check();
}
else { System.out.println("no"); }
}
});
void check(){
System.out.println("in checking condition");
if((lb11==la11) && (lb12==la12) && (lb13==la13) && (lb21==la21) && (lb22==la22)
&& (lb23==la23) && (lb31==la31) && (lb32==la32) && (lb33==la33)) {
Context c = getBaseContext();
System.out.println("gameover");
Toast.makeText(c, " GameOver ", Toast.LENGTH_SHORT).show();
}else{ System.out.println(" codition not checked "); }
}
//here lb=level before sliding
// la=level after sliding..
Ok, here is what you do for the solution.
maintain a new set of drawables marking them as original drawables that you had initially.
may be like
drawable og11 = imageView11.getDrawable();
do this part before shuffling. now you have original drawables, stored in the form of drawables.
After every click , check if og11 == imageView11.getDrawable(),... and so on for all the images in the jigsaw, if they match , it matches, else, they don't.
HTH.
I have a simple solution. Set serial number Integer tags to ImageViews using View.setTag(index) before jumbling(before preparing the puzzle.) Then everytime the user makes a move, loop through all the imageviews and check if they are in order. If out of order then puzzle is not completed yet.
class PuzzleItem {
Drawable puzzlepartImage;
int correctPosition;
public PuzzleItem(Drawable d, int index) {
puzzlepartImage = d;
correctPosition = index;
}
}
ArrayList<PuzzleItem> list = new ArrayList<PuzzleItem>();
for (int i = 0; i < 9; i++) {
list.add(new PuzzleItem(drawables[i], i));
}
Collections.shuffle(list);
//Create the views from this list and add to the layout serially.
// set the last view as emptyview.
On every move:
void onClick(View v) {
/* swap drawables */
Drawable clickedDrawable = v.getDrawable();
v.setDrawable(null);
mEmptyView.setDrawable(clickedDrawable);
mEmptyView = v;
/* swap tag integers */
Integer temp = (Integer)mEmptyView.getTag();
mEmptyView.setTag(v.getTag());
v.setTag(temp);
}
After every move check for completion:
for (int i = 0; i < 9; i++) {
if (imgView[i].getTag() != i) break;
}
if (i == 9)// puzzle completed.
why don't you use a gridView? and after each change, just check the items to see that images are in desired order
When you use == operator they are checking if both the objects are referencing the same object. But in your case they are 2 different objects.
You should set a tag to both the actual image and the other image. And check if they are both the same. That should work in your if condition.
For the drawable class i did notice a method setLevel and getLevel. You might be able to use this for your requirement.

Categories

Resources