I want to validate text input, but how to show multiple edit text error simultaneously??
Here is my code
binding.btnCalculate.setOnClickListener() {
val panjang = binding.etPanjang.text
val lebar = binding.etLebar.text
val tinggi = binding.etTinggi.text
if (TextUtils.isEmpty(binding.etPanjang.text)) {
binding.etPanjang.setError("Field must be filled")
} else if (TextUtils.isEmpty(binding.etLebar.text)) {
binding.etLebar.setError("Field must be filled")
} else if (TextUtils.isEmpty(binding.etLebar.text)) {
binding.etTinggi.setError("Field must be filled")
} else {
val action = InputFragmentDirections.actionInputFragmentToOutputFragment(
panjang.toString().toInt(),
lebar.toString().toInt(),
tinggi.toString().toInt()
)
findNavController().navigate(
action
)
}
}
Result
I Want all edit text that empty is showing error, not only one edit text
You just need to change if .. else to if only for each condition so each condition can be checked and set error if input is not valid
replace your code with below
binding.btnCalculate.setOnClickListener() {
val panjang = binding.etPanjang.text
val lebar = binding.etLebar.text
val tinggi = binding.etTinggi.text
var isAnyError = false
if (TextUtils.isEmpty(binding.etPanjang.text)) {
binding.etPanjang.setError("Field must be filled")
isAnyError = true
}else{
binding.etPanjang.setError(null)
}
if (TextUtils.isEmpty(binding.etLebar.text)) {
binding.etLebar.setError("Field must be filled")
isAnyError = true
}else{
binding.etLebar.setError(null)
}
if (TextUtils.isEmpty(binding.etLebar.text)) {
binding.etTinggi.setError("Field must be filled")
isAnyError = true
}else{
binding.etTinggi.setError(null)
}
if(!isAnyError){
val action = InputFragmentDirections.actionInputFragmentToOutputFragment(
panjang.toString().toInt(),
lebar.toString().toInt(),
tinggi.toString().toInt()
)
findNavController().navigate(
action
)
}
}
im working on a new chromecast app
mCastContext?.let { nCastContext ->
if (mCastPlayer == null) {
mCastPlayer = CastPlayer(nCastContext)
}
mCastPlayer?.let { nCastPlayer ->
nCastPlayer.clearMediaItems()
val mMediaItem = when (nPlayerInput.mCastData.mFormat) {
StreamRequest.StreamFormat.DASH -> getDashMedia(nPlayerInput.mCastData)
StreamRequest.StreamFormat.HLS -> getHlsMedia(nPlayerInput.mCastData)
else -> null
}
mMediaItem?.let { nMedia ->
val mMediaQueue: ArrayList<MediaItem> = ArrayList()
mMediaQueue.add(nMedia)
nCastPlayer.setSessionAvailabilityListener(CastSessionAvailabilityListener(this))
nCastPlayer.addListener(CastEventListener(this))
nCastPlayer.playWhenReady = true
nCastPlayer.setMediaItems(ArrayList(mMediaQueue), 0, 0)
nCastPlayer.prepare()
nCastPlayer.play()
Log.d("fromCast","PLAY")
}?:run {
mInterface?.fromCastToLog("CAST_100",true)
}
}?:run {
mInterface?.fromCastToLog("CAST_101",true)
}
}
and
fun getDashMedia(nAsset: PlayerCastData): MediaItem {
return MediaItem.Builder()
.setUri(nAsset.mUrl)
.setCustomCacheKey("bala")
.setMediaMetadata(MediaMetadata.Builder().setTitle(nAsset.mTitle).setSubtitle(nAsset.mSubtitle).build())
.setMimeType(MimeTypes.APPLICATION_MPD)
.setDrmConfiguration(MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID)
.setLicenseUri(nAsset.mProxy).build())
.build()
}
How can i add stream/vod image to be displayed on CastControlActivity ? Im using androidx.media3
Im my prev old version i was able to add image and custom data using MediaMetadata. But now i can only user setTitle, setSubtitle and others but i can not see how to add image
Thx
In the following code, I have two parts A and B. I need to extract part B as a common part for more of my pages.
But it contains item, I cannot extract item, but item must be included in the if judgment because paging3 will scroll to the top for extra item.
Is there a way to extract item?
LazyColumn(Modifier.fillMaxSize()) {
// Part A
items(pagingItems) { wind ->
WindRow(navController, wind!!)
}
val refresh = pagingItems.loadState.refresh
val append = pagingItems.loadState.append
// Part B
if (refresh is LoadState.NotLoading && append is LoadState.NotLoading) {
if (pagingItems.itemCount == 0) {
item {
PosterCompose() {
navController.navigate("blowWind")
}
}
}
} else {
item {
LoadStateView(path = FOLLOW_WIND_LIST, refresh = refresh, append = append) {
pagingItems.retry()
}
}
}
}
I solved this problem
fun <T : Any> LazyListScope.newItems(pagingItems: LazyPagingItems<T>) {
val refresh = pagingItems.loadState.refresh
val append = pagingItems.loadState.append
if (refresh is LoadState.NotLoading && append is LoadState.NotLoading) {
if (pagingItems.itemCount == 0) {
item {
PosterCompose() {
}
}
}
}else{
item {
LoadStateView(path = FOLLOW_WIND_LIST, refresh = refresh, append = append) {
pagingItems.retry()
}
}
}
}
This is how to use
LazyColumn(Modifier.fillMaxSize()) {
items(pagingItems) { wind ->
WindRow(navController, wind!!)
}
newItems(pagingItems)
}
I am trying to make TicTacToe Application, I have already implemented the "player Vs player" part but I am having trouble with implementing the player Vs computer. I have a function called playgame. For update_player I am doing manually and for update computer, I am doing it using random, and I think this is causing the issue as I am checking if my boardStatus is already filled, if it's filled I am calling my function again. I read online that all the calculation should be done on thread, I tried implementing it but I think I am doing it wrong. Please Help!
Here's my code for reference:
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import kotlinx.android.synthetic.main.activity_computer.*
import java.util.*
class ComputerActivity : AppCompatActivity() {
var player = true
var turnCount = 0
var boardStatus = Array(3) { IntArray(3) }
lateinit var board: Array<Array<Button>>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_computer)
board = arrayOf(
arrayOf(First, Second, Third),
arrayOf(Fourth, Fifth, Sixth),
arrayOf(Seventh, Eighth, Ninth)
)
playGame()
}
private fun playGame(){
Status.text = "Player's Turn"
for (i in 0..2) {
var flag: Boolean = false
for (j in 0..2) {
if (player) {
Status.text = "Player's Turn"
update_player(player)
Thread.sleep(2000)
player = false
turnCount++
checkWinner()
if (turnCount == 9) {
Status.text = "Game Draw"
flag = true;
}
} else {
Status.text = "Computer's Turn"
update_computer(player)
Thread.sleep(2000)
player = true
turnCount++
checkWinner()
if (turnCount == 9){
Status.text = "Game Draw"
flag = true
}
}
}
if(flag == true)
break
}
changeBoard()
resetBtn.setOnClickListener{
player = true;
turnCount = 0
changeBoard()
}
}
private fun update_player(player:Boolean){
for(i in board){
for(button in i){
button.setOnClickListener{
when(it.id){
R.id.First->{
updateBoardStatus(row = 0, column = 0,player)
}
R.id.Second->{
updateBoardStatus(row = 0, column = 1,player)
}
R.id.Third->{
updateBoardStatus(row = 0, column = 2,player)
}
R.id.Fourth->{
updateBoardStatus(row = 1, column = 0,player)
}
R.id.Fifth->{
updateBoardStatus(row = 1, column = 1,player)
}
R.id.Sixth->{
updateBoardStatus(row = 1, column = 2,player)
}
R.id.Seventh->{
updateBoardStatus(row = 2, column = 0,player)
}
R.id.Eighth->{
updateBoardStatus(row = 2, column = 1,player)
}
R.id.Ninth->{
updateBoardStatus(row = 2, column = 2,player)
}
}
}
}
}
}
private fun update_computer(player:Boolean){
var row:Int = 0
var column:Int = 0
Thread {
row = (0..2).random()
column = (0..2).random()
}.start()
if(boardStatus[row][column] == 0 || boardStatus[row][column]==1)
update_computer(player)
else
updateBoardStatus(row, column, player)
}
private fun updateBoardStatus(row:Int, column:Int, player:Boolean){
val text = if (player) "X" else "0"
val value = if (player) 1 else 0
board[row][column].apply {
isEnabled = false
setText(text)
}
boardStatus[row][column] = value
}
private fun checkWinner(){
//Horizontal --- rows
for (i in 0..2) {
if (boardStatus[i][0] == boardStatus[i][1] && boardStatus[i][0] == boardStatus[i][2]) {
if (boardStatus[i][0] == 1) {
result("Player Won!!")
break
} else if (boardStatus[i][0] == 0) {
result("Computer Won")
break
}
}
}
//Vertical --- columns
for (i in 0..2) {
if (boardStatus[0][i] == boardStatus[1][i] && boardStatus[0][i] == boardStatus[2][i]) {
if (boardStatus[0][i] == 1) {
result("Player Won!!")
break
} else if (boardStatus[0][i] == 0) {
result("Computer Won!!")
break
}
}
}
//First diagonal
if (boardStatus[0][0] == boardStatus[1][1] && boardStatus[0][0] == boardStatus[2][2]) {
if (boardStatus[0][0] == 1) {
result("Player Won!!")
} else if (boardStatus[0][0] == 0) {
result("Computer won!!")
}
}
//Second diagonal
if (boardStatus[0][2] == boardStatus[1][1] && boardStatus[0][2] == boardStatus[2][0]) {
if (boardStatus[0][2] == 1) {
result("Player Won!!")
} else if (boardStatus[0][2] == 0) {
result("Computer Won!!")
}
}
}
private fun result(res:String){
Status.text = res
if(res.contains("Won")){
disableButton()
}
else{
}
}
private fun disableButton(){
for(i in board){
for(button in i){
button.isEnabled = false
}
}
}
private fun changeBoard(){
for (i in 0..2) {
for (j in 0..2) {
boardStatus[i][j] = -1
}
}
for (i in board) {
for (button in i) {
button.isEnabled = true
button.text = ""
}
}
}
}
Your code is trying to put the whole sequence of actions of the game in a function that is called once and then expects player button-presses to happen internally. Button listeners will fire some time in the future, after the function already returns. You need to think in terms of there being a function that is called each time a button is pressed to do the next stage of the game.
To fix this:
Remove the playGame() function.
Remove the player parameter from update_player() since it's always true. And change the function name to initializeButtons. Call it once in onCreate(). You only have to add listeners to the buttons one time and they will work repeatedly.
Also remove the player parameter from update_computer() for the same reason as above. And remove the threading so it looks like:
private fun update_computer() {
val row = (0..2).random()
val column = (0..2).random()
if (boardStatus[row][column] == 0 || boardStatus[row][column] == 1)
update_computer()
else
updateBoardStatus(row, column, player)
}
Then at the end of the updateBoardStatus function call checkWinner(). checkWinner() should return a Boolean, so in updateBoardStatus(), if no win condition has been found and player is true, it should call update_computer().
So what you have now instead of trying to run the game from one function, you set up button listeners one time to start the game. When a button is pressed, it takes the player turn, which then triggers updateBoardStatus, which then triggers the computer turn, which then triggers updateBoardStatus again, and then does nothing if no one won. All of that happens synchronously/instantly on the main thread, so now the game is back to waiting for a button press from the user to repeat the sequence of events.
Also, the status text view has limited usefulness. Since the computer takes its turns instantly, it's not possible to ever see the words "Computer's turn". If you want to do that, you'll have to create an artificial delay, so you would have to disable all the buttons and then do something like call postRunnable({ startPlayerTurn() }, 1000L), where the startPlayerTurn() re-enables the appropriate buttons and makes it say, "Player turn" again.
class MainActivity : AppCompatActivity() {
enum class PLAYINGPLAYER {
FIRST_PLAYER,
SECOND_PLAYER
}
var playingplayer: PLAYINGPLAYER? = null
var buttonClicked:ArrayList<Int> = ArrayList()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
playingplayer = PLAYINGPLAYER.FIRST_PLAYER
}
fun imgButtonClicked(v: View) {
val btnselected = v as Button
var optionNumber = 0
when (btnselected.id) {
R.id.btn1 -> optionNumber = 1
R.id.btn2 -> optionNumber = 2
R.id.btn3 -> optionNumber = 3
R.id.btn4 -> optionNumber = 4
R.id.btn5 -> optionNumber = 5
R.id.btn6 -> optionNumber = 6
}
action(optionNumber, btnselected)
}
var button1Click = ArrayList<Button>()
var button2Click = ArrayList<Button>()
fun action(optionNumber: Int, btnselected: Button) {
if (playingplayer == PLAYINGPLAYER.FIRST_PLAYER) {
btnselected.setBackgroundColor(Color.GREEN)
buttonClicked.add(optionNumber)
btnselected.isEnabled = false
button1Click.add(btnselected)
playingplayer = PLAYINGPLAYER.SECOND_PLAYER
}
else if (playingplayer == PLAYINGPLAYER.SECOND_PLAYER) {
btnselected.setBackgroundColor(Color.RED)
buttonClicked.add(optionNumber)
btnselected.isEnabled = false
button2Click.add(btnselected)
playingplayer = PLAYINGPLAYER.FIRST_PLAYER
}
imagebtnState()
}
fun imagebtnState() {
val btnLast = buttonClicked.get(buttonClicked.size - 1)
if (buttonClicked.contains(1) && buttonClicked.contains(2)) {
if ( btnLast == ??? player1 ) {
imgbBtnBackground.setImageResource(R.drawable.rca)
}
}
else if (buttonClicked.contains(1) && buttonClicked.contains(2)) {
if ( btnLast == ??? player2 ) {
imgbBtnBackground.setImageResource(R.drawable.wac)
}
}
}
}
I have two players and several buttons. Player1 clicks on a button and player2 clicks on another button. When the players press several specific ?, I want to change the background of imageButton.
In (btnLast = ???) what I have put to get last one click in (buttonClicked.contains(1) && buttonClicked.contains(2)) is player1 or player2.
Assuming you are only ever going to have two players create a boolean called var playerOneLastClicked = true and if player one clicks set true, else if player two clicks set false
if (buttonClicked.contains(1) && buttonClicked.contains(2)) {
if (playerOneLastClicked) {
imgbBtnBackground.setImageResource(R.drawable.rca)
} else {
imgbBtnBackground.setImageResource(R.drawable.wac)
}
}
Since imagebtnState() is called after each click it doesn't really matter about checking who clicked the last in the arrayList as the method does the check to see whether or not the specified buttons have been clicked anyway
I think that's that what you were asking for?