when a item is pressed I want to modify a value declared outside the onCreate method. But when the item is pressed, the onTouchListener does the other functions except modify that value. I've tried to write the same instruction to modify the value outside the onTouchListener method and it worked. This is my code:
class MainActivity : AppCompatActivity() {
var ciao: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var listenerUser = View.OnTouchListener(function = { view, motionEvent ->
if (motionEvent.action == MotionEvent.ACTION_DOWN) {
this.ciao = "ciao"
}
true
})
}
override fun onResume() {
super.onResume()
if (ciao != null) {
println(ciao!!)
}
}
}
When my application resumes the var ciao is null, but if I put this.ciao = "ciao" outside the listener the var isn't null.
You need to set your OnTouchListener for the view that should react:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val listener = View.OnTouchListener(function = {view, motionEvent ->
if (motionEvent.action == MotionEvent.ACTION_DOWN) {
this.ciao = "ciao"
}
true
})
clickedView.setOnTouchListener(listener)
}
If you just want to detect a click you are probably better off using a OnClickListener like this:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
clickedView.setOnClickListener(_ ->
this.ciao = "ciao"
)
}
Related
I am passing TextToSpeech from Fragment to my RecyclerView Adapter.
While passing it, I am also sending a flag textToSpeechSupported to confirm whether the currently set device language is supported for TextToSpeech announcement or not.
But every time the value of this flag is being set as false, even though I am setting the value to true in onCreate.
It seems there is an issue with my implementation approach.
But I tired to debug and also added Logs.
Also I did multiple test and tried various other combinations. But every time the flag textToSpeechSupported value is being passed is false, even if the language is supported.
Am I missing something here.
I need the flag textToSpeechSupported value to be true if the device language is supported by TextToSpeech
Please guide.
class WelcomeFragment : Fragment() {
private lateinit var welcomeAdapter: WelcomeAdapter
private lateinit var textToSpeech: TextToSpeech
private var textToSpeechSupported: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
textToSpeech = TextToSpeech(requireContext()) { status ->
if (status == SUCCESS) {
val result = textToSpeech.setLanguage(Locale.getDefault())
textToSpeechSupported =
!(result == TextToSpeech.LANG_NOT_SUPPORTED || result == TextToSpeech.LANG_MISSING_DATA)
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
welcomeAdapter = WelcomeAdapter(textToSpeech, textToSpeechSupported)
binding.adapter = welcomeAdapter
}
}
class Welcomedapter(private val textToSpeech: TextToSpeech, private val textToSpeechSupported: Boolean) : ListAdapter<Welcome, ViewHolder>(WelcomeDiffCallback()) {
//....
class ViewHolder private constructor(val binding: ContainerWelcomeBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: Welcome, textToSpeech: TextToSpeech, textToSpeechSupported: Boolean) {
binding.apply {
welcomeMessageText.text = item.welcome
textToSpeechImage.setOnClickListener {
if (textToSpeechSupported) {
textToSpeech.speak(item.welcome, TextToSpeech.QUEUE_FLUSH, null)
} else {
// Send an event for Toast saying that language is not supported for Text to Speech
}
}
}
}
}
}
The objective/goal is to ensure that value of flag textToSpeechSupported is correctly calculated and passed to Recycler View Adapter.
The problem is that onViewCreated is being called BEFORE the tts has had time to initialize, so you are accessing textToSpeechSupported too early and you're always getting your default (false) value.
So, instead of calling:
welcomeAdapter = WelcomeAdapter(textToSpeech, textToSpeechSupported)
binding.adapter = welcomeAdapter
from inside onViewCreated, make a new function:
fun thisFunctionRunsAFTERtheTTSisInitialized() {
// put that code here instead.
}
And then call that function from inside your onCreate so it will run AFTER the tts has initialized:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
textToSpeech = TextToSpeech(requireContext()) { status ->
if (status == SUCCESS) {
val result = textToSpeech.setLanguage(Locale.getDefault())
textToSpeechSupported =
!(result == TextToSpeech.LANG_NOT_SUPPORTED || result == TextToSpeech.LANG_MISSING_DATA)
thisFunctionRunsAFTERtheTTSisInitialized() // <---------------
}
}
}
It would be better to pass an interface or function to adapter
e.g
class Welcomedapter(private val block : () -> Unit) : ListAdapter<Welcome, ViewHolder>(WelcomeDiffCallback()) {
//....
class ViewHolder private constructor(val binding: ContainerWelcomeBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: Welcome, textToSpeech: TextToSpeech, textToSpeechSupported: Boolean) {
binding.apply {
welcomeMessageText.text = item.welcome
textToSpeechImage.setOnClickListener {
block()
}
}
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
welcomeAdapter = WelcomeAdapter {
if (textToSpeechSupported) {
textToSpeech.speak(item.welcome, TextToSpeech.QUEUE_FLUSH, null)
} else {
// show the toast here now
}
}
binding.adapter = welcomeAdapter
}
I want to perform the actions when the button is pressed not just clicked
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var ib:ImageView=findViewById(R.id.imageView4) as ImageView
var final=MediaPlayer.create(this,R.raw.`m1`)
var anim=AnimationUtils.loadAnimation(this,R.anim.rotate)
ib.setOnTouchListener(){
textView.text="rip"
final.start();
ib.startAnimation(anim);
}
}
}
I want the actions to be performed when the button is held and stop when they are not .
this seems to be working fine but the compiler gives a warning
ib.setOnTouchListener(View.OnTouchListener { view, motionEvent ->
when (motionEvent.action){
MotionEvent.ACTION_DOWN -> {
textView4.text="IGNORING"
ib.startAnimation(anim)
final.setLooping(true)
final.start()
}
MotionEvent.ACTION_UP -> {
textView4.text="IGNORE"
ib.clearAnimation()
final.pause()
}
}
return#OnTouchListener true
})
I want to expand and collapse a CollapsingToolBar in android studio
when i click a button.
I want it collapsed by dafault. Im doing something wrong and i dont know what, thanks for the help.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//maybe this doesnt go here, im trying to make it collapse by default
var start = appbar.setExpanded(false)
button.setOnClickListener {
if(start == appbar.setExpanded(false)){
start = appbar.setExpanded(true)
}else{
start = appbar.setExpanded(false)
}
}
}
Try this:
class MainActivity : AppCompatActivity() {
private var isAppbarExpanded = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
if(!isAppbarExpanded){
appbar.setExpanded(true)
isAppbarExpanded = true
}else{
appbar.setExpanded(false)
isAppbarExpanded = false
}
}
}
I'm trying to reset a button to become clickable once a key on the keyboard is pressed. It works with the hardware keyboard but not with the emulator keyboard. How would one implement this?
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.log_in_button)
val email = findViewById<EditText>(R.id.email_field)
button.isClickable = false
button.alpha = .5f
email.setOnKeyListener(object : View.OnKeyListener {
override fun onKey(v: View, keyCode: Int, event: KeyEvent): Boolean {
if(event.action == KeyEvent.ACTION_DOWN) {
button.isClickable = true
button.alpha = 1f
return true
}
return false
}
})
}
Here is my kotlin/android activity:
import kotlinx.android.synthetic.main.activity_player_details.*
class PlayerDetails : AppCompatActivity(), View.OnClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_player_details)
val intent = getIntent()
val numOfPlayers = intent.getIntExtra("number_of_players", 1)
next_details.setOnClickListener(this)
}
override fun onClick(v: View?) {
for (player in 1..numOfPlayers) {
// body in here
}
}
}
I want to pass the value of numOfPlayers to my onClick method so I can use it - how can I achieve this?
Either make numOfPlayer as global variable or create separate function to call when btn is clicked and pass numOfPlayer as parameter
1. make numOfPlayer as global variable
class PlayerDetails : AppCompatActivity(), View.OnClickListener {
var numOfPlayers = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_player_details)
val intent = getIntent()
numOfPlayers = intent.getIntExtra("number_of_players", 1)
next_details.setOnClickListener(this)
}
override fun onClick(v: View?) {
for (player in 1..numOfPlayers) {
// body in here
}
}
}
2. create separate function to call when btn is clicked and pass numOfPlayer as parameter
class PlayerDetails : AppCompatActivity(), View.OnClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_player_details)
val intent = getIntent()
val numOfPlayers = intent.getIntExtra("number_of_players", 1)
bottomNav.setOnClickListener {
onNextClick(numOfPlayers)
}
}
private fun onNextClick(numOfPlayers: Int) {
for (player in 1..numOfPlayers) {
// body in here
}
}
}
Define your variable with global scope like below
var numOfPlayers = 0
Make sure to define it above onCreate() method.
onCreate is called when the activity is created, and onClick is called when the next_details button is clicked, which definitely happens after onCreate.
So make numOfPlayers a class member and assign the value to it in onCreate, and also add the lateinit keyword to numOfPlayers so you don't need to make it nullable.
The code should look like this:
import kotlinx.android.synthetic.main.activity_player_details.*
class PlayerDetails : AppCompatActivity(), View.OnClickListener {
lateinit var numOfPlayers: Integer
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_player_details)
val intent = getIntent()
numOfPlayers = intent.getIntExtra("number_of_players", 1)
next_details.setOnClickListener(this)
}
override fun onClick(v: View?) {
for (player in 1..numOfPlayers) {
// body in here
}
}
}
Make numOfPlayers global
var numOfPlayers =0
In onCreate()
val intent = getIntent()
numOfPlayers = intent.getIntExtra("number_of_players", 1)
In onClick()
for (i in 1..numOfPlayers) {
// body in here
}