CalendarView doesn't reset after getDate() - android

I am trying to get the numerical value of a date out of a CalendarView, which should be possible by using calendarView.date. I have attached this function to a button that displays the long calendarView.date in a TextView. It works fine the first time I press the button but doesn't update the TextView when I select a new date and press the button again.
Here's my MainActivity.kt:
package com.androidas.mindscape
import android.app.Activity
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.Menu
import android.view.MenuItem
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.tlbMain))
}
override fun onCreateOptionsMenu(menu:Menu):Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.toolmenu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.actAdd -> {
textView2.text = "reset" //my idea was to reset the text first, but this didn't work.
textView2.text = (clvMain.date).toString()
true
}
R.id.actPersonalities -> {
// User chose the "Favorite" action, mark the current item
// as a favorite...
true
}
R.id.actList -> {
true
}
else -> {
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
super.onOptionsItemSelected(item)
}
}
}
Where R.id.actAdd is an item in the overflow menu of the action bar.
The way I see it, the TextView should update with the newly selected date as soon as I press the button. Any ideas? Maybe it's simple, but I can't figure it out.
Cheers!

Add this declaration var dateString: String = Date().toString() before onCreate().
Add this code in onCreate():
clvMain.setOnDateChangeListener { view, year, month, dayOfMonth ->
dateString = "$year/$month/$dayOfMonth"
}
and use dateString instead of (clvMain.date).toString()

Related

Stuck in Kotlin coding to do the Calendar page with a library in Android Studio

I want to do the calendar page in Kotlin which I imported library from hi-manshu/Kalendar. I want to do the calendar page in Month view. So, I use firey (from the document https://github.com/hi-manshu/Kalendar/blob/main/docs/Kalendar.md) to set it. I also want to do the other stuffs from the document such as Calendar header, Setting up Events, change Calendar color, etc. But I have no ideas how to do.
This is where I'm right now.
package com.example.calendar
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.himanshoe.kalendar.model.KalendarType
class MainActivity : AppCompatActivity() {
private lateinit var kalendarView: KalendarView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
kalendarView = findViewById(R.id.kalendarView)
// Customize the KalendarView with the Oceanic type
kalendarView.kalendarType = KalendarType.Firey
kalendarView.setSelectionMode(KalendarView.SelectionMode.SINGLE)
kalendarView.setStartDate("2022-01-01")
kalendarView.setEndDate("2022-12-31")
kalendarView.setOnDateSelectedListener { date ->
// Handle the date selection
}
}

lateinit property action has not been initialized in kotlin, how to fix it?

import android.app.Dialog
import android.app.TimePickerDialog
import android.os.Bundle
import android.text.format.DateFormat
import android.widget.TimePicker
import androidx.fragment.app.DialogFragment
import java.util.*
class TimePickerFragment : DialogFragment(), TimePickerDialog.OnTimeSetListener {
lateinit var action : (String) -> Unit
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
// Use the current time as the default values for the picker
val c = Calendar.getInstance()
val hour = c.get(Calendar.HOUR_OF_DAY)
val minute = c.get(Calendar.MINUTE)
// Create a new instance of TimePickerDialog and return it
return TimePickerDialog(activity, this, hour, minute, DateFormat.is24HourFormat(activity))
}
override fun onTimeSet(view: TimePicker, hourOfDay: Int, minute: Int) {
var min = minute.toString()
if(min.toInt() < 10) min = "0$min"
action("$hourOfDay:$min")
}
fun setListener(action: (String) -> Unit) {
this.action = action
}
}
my declare action was detected error in firebase inside fun setlistener this.action=action how to fix it? sorry i am newbie guys, i am need more references , thank you
The lateinit field holds a reference to the listener that does something with the result of the time that you've picked.
So if you show the picker dialog without setting that listener first, when the onTimeSet(..) function is called, which happens when you tap "OK" on the picker dialog, the action field still hasn't been initialised, so an UninitializedPropertyAccessException will be thrown.
You just need to set the action listener using the setListener(..) function beforehand. It can even be empty as shown below.
val dialog = TimePickerFragment()
dialog.setListener {
// your listener logic
}
dialog.show(supportFragmentManager, "fragment-tag")
Update: In onTimeSet, you are passing a string to action(..). In your code, action is a listener that does something with the string that you pass to it. But you are passing a String to the listener before it has been set to anything, that is why you are seeing an error.
lateinit fields must be set before they can be used.
The quickest modification to your existing class would be to apply a listener by default:
// Create a new instance of TimePickerDialog and return it
return TimePickerDialog(activity, this, hour, minute, DateFormat.is24HourFormat(activity)).apply {
action = { dateTimeString ->
Log.d("LOG_TAG", "Time Selected -> $dateTimeString") // this outputs the String defined in onTimeSet to Logcat
}
}
Then if you want to assign a different listener, you do so with setListener().
Just before the function that uses the variable or instance, initialise it to a reasonable value or use this if its part of the class constructors

Need to take user to a different page when they click on a list item/ convert current list items to buttons?

I was trying to create a search function such that if a user searches for an item, the excessive items go away as they search on the toolbar and when they click on the item it takes them to the specific page for that item. Currently, I have this code which I salvaged by watching someone on youtube, I need help as I'm a total beginner. Thanks!
college_search.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/college_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.testrun3.CollegeSearch"/>
CollegeSearch.kt
package com.example.testrun3
import android.content.Context
import androidx.recyclerview.widget.RecyclerView
import androidx.appcompat.widget.SearchView
import android.view.LayoutInflater
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.GridLayoutManager
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.college_search.*
import kotlinx.android.synthetic.main.country_child.view.*
import android.os.Bundle as Bundle1
class CollegeSearch : AppCompatActivity() {
var countries:MutableList<String> = ArrayList()
var displayList:MutableList<String> = ArrayList()
override fun onCreate(savedInstanceState: Bundle1?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.college_search)
loadData()
// country_list.layoutManager = LinearLayoutManager(this)
college_list.layoutManager = GridLayoutManager(this,1)
college_list.adapter = CountryAdapter(displayList,this)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.main,menu)
val searchItem = menu.findItem(R.id.college_search_menu)
if(searchItem != null){
val searchView = searchItem.actionView as SearchView
val editext = searchView.findViewById<EditText>(androidx.appcompat.R.id.search_src_text)
editext.hint = "Search here..."
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener{
override fun onQueryTextSubmit(query: String?): Boolean {
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
displayList.clear()
if(newText!!.isNotEmpty()){
val search = newText.toLowerCase()
countries.forEach {
if(it.toLowerCase().contains(search)){
displayList.add(it)
}
}
}else{
displayList.addAll(countries)
}
college_list.adapter?.notifyDataSetChanged()
return true
}
})
}
return super.onCreateOptionsMenu(menu)
}
class CountryAdapter(items : List<String>,ctx:Context) : RecyclerView.Adapter<CountryAdapter.ViewHolder>(){
private var list = items
private var context = ctx
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder?.name?.text = list[position]
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(context).inflate(R.layout.country_child,parent,false))
}
class ViewHolder(v: View) : RecyclerView.ViewHolder(v){
val name = v.country_name!!
}
}
private fun loadData(){
countries.add("Afghanistan")
countries.add("Albania")
countries.add("Algeria")
countries.add("Andorra")
countries.add("Angola")
countries.add("Antigua and Barbuda")
countries.add("Argentina")
countries.add("Armenia")
countries.add("Australia")
countries.add("Austria")
countries.add("Azerbaijan")
countries.add("Bahamas")
countries.add("Bahrain")
countries.add("Bangladesh")
countries.add("Barbados")
countries.add("Belarus")
countries.add("Belgium")
countries.add("Belize")
countries.add("Benin")
countries.add("Bhutan")
countries.add("Bolivia")
countries.add("Bosnia and Herzegovina")
countries.add("Botswana")
countries.add("Brazil")
countries.add("Brunei")
countries.add("Bulgaria")
countries.add("Burkina Faso")
countries.add("Burundi")
countries.add("Cabo Verde")
countries.add("Cambodia")
countries.add("Cameroon")
countries.add("Canada")
countries.add("Central African Republic (CAR)")
countries.add("Chad")
countries.add("Chile")
countries.add("China")
countries.add("Colombia")
countries.add("Comoros")
countries.add("Democratic Republic of the Congo")
countries.add("Republic of the Congo")
countries.add("Costa Rica")
countries.add("Cote d'Ivoire")
countries.add("Croatia")
countries.add("Cuba")
countries.add("Cyprus")
countries.add("Czech Republic")
countries.add("Denmark")
countries.add("Djibouti")
countries.add("Dominica")
countries.add("Dominican Republic")
countries.add("Ecuador")
countries.add("Egypt")
countries.add("El Salvador")
countries.add("Equatorial Guinea")
countries.add("Eritrea")
countries.add("Estonia")
countries.add("Ethiopia")
countries.add("Fiji")
countries.add("Finland")
countries.add("France")
countries.add("Gabon")
countries.add("Gambia")
countries.add("Georgia")
countries.add("Germany")
countries.add("Ghana")
countries.add("Greece")
countries.add("Grenada")
countries.add("Guatemala")
countries.add("Guinea")
countries.add("Guinea-Bissau")
countries.add("Guyana")
countries.add("Haiti")
countries.add("Honduras")
countries.add("Hungary")
countries.add("Iceland")
countries.add("India")
countries.add("Indonesia")
displayList.addAll(countries)
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:title="Search"
android:id="#id/college_search_menu"
android:icon="#android:drawable/ic_menu_search"
app:showAsAction="always|collapseActionView"
app:actionViewClass="androidx.appcompat.widget.SearchView"
/>
</menu>
First, you create an OnClickListener in onBindViewHolder() of your CountryAdapter
holder.name.setOnClickListener {
val intent = Intent(context, YourActivity::class.java)
context!!.startActivity(intent)
}
This is how you set an OnClickListener on an item in Adapter. Here's we're using intent to start a different activity when the item is clicked.
Now, Intent class in the above solution takes two parameters, First one is the Context which is the current activity with which user is interacting. This is used to pass the current focus where new activity should open. It must not be null. Second one is the activity's class you want the app to switch to. Activity opens in stack which means Last in First Out.
Next, you're starting the created intent by using startActivity(Intent). But, as this is not an Activity, you have to pass the context to it as well. But, where's the context?
Here: class CountryAdapter(items : List<String>,ctx:Context). See, you've already declared it as an argument and also passing it from the activity as college_list.adapter = CountryAdapter(displayList,this). This this is the context you've passed to the Adapter.
I said use ctx. Why? because you've named the context ctx in your adapter which doesn't matter because it's a variable and you can name it as you like. Same context mechanism is needed in Fragments.
Also. remember, in activity you pass this as context as parameter but don't need it for invoking methods like startActivity().
So, final result for your adapter's or a Fragment's onClickListener is:
holder.name.setOnClickListener {
val intent = Intent(ctx, YourActivity::class.java)
ctx.startActivity(intent)
}
In case of an activity is:
//In activity, you don't even need to pass the rootView to access the elemets as in adapter or Fragments.
name.setOnClickListener {
val intent = Intent(this, YourActivity::class.java)
startActivity(intent)
}
Now, you just have to design a new activity for the item. Also, With so many multiple items, you wouldn't want to create as many activities. So, Create a same structured activity, pass the selected item to it and do whatever you want to do with the item.
You can do it by passing the selected item through intent using the .putExtra().
//It takes two parameters: First one is the key name you want to give to the value passed
//Second one is the actual value you pass
intent.putExtra("SelectedCountry",list[position])
//This will put the selected country with the intent request.
//put it before just startActivity
Now, access it in the next activity as:
//Here, you have to use the data type based extra for the value you've passed.
//As we have passed a string, we're using getStringExtra, same for int getIntExtra()
//It takes the key name as the input, key should exactly match in both the activities
val selectedCountry = intent.getStringExtra("SelectedCountry")
//Now, do whatever you want with this country name in the new activity.
This is a very detailed answer, I hope you'll learn it all. Also, you'll learn eventually.

Toggling visibility in Kotlin, isVisible unresolved reference

Slowly learning Kotlin. Just generating a random number from a roll. If roll = 9 I want to make the button and seekbar invisible.
I'm using the toggleVisibility function to accomplish this, but the Kotlin compiler sees isVisible as a unresolved reference
package com.example.randomizer
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.SeekBar
import android.widget.TextView
import android.widget.VideoView
import java.util.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rollButton = findViewById<Button>(R.id.rollButton)
val resultsTextView = findViewById<TextView>(R.id.resultsTextView)
val seekBar = findViewById<SeekBar>(R.id.seekBar)
val winText = "9 You Win !"
rollButton.setOnClickListener {
val rand = Random().nextInt(seekBar.progress)
resultsTextView.text = rand.toString()
if (rand == 9) {
resultsTextView.text = winText
seekBar.toggleVisibility()
rollButton.toggleVisibility()
}
}
}
fun View.toggleVisibility() {
if (this.isVisible()) {
this.visibility = View.INVISIBLE
} else {
this.visibility = View.VISIBLE
}
}
}
Compiler error:
unresolved reference isVisible
As others mentioned above, you can either specify isVisible() as an extension function by yourself.
fun View.isVisible() = this.visibility == View.Visible
Or you can add the KTX view dependency and start using some of the methods there. I recommend you have a look at: https://developer.android.com/reference/kotlin/androidx/core/view/package-summary#(android.view.View).isVisible:kotlin.Boolean
To import and start using KTX add to your Dependencies in build.gradle
implementation "androidx.core:core-ktx:1.0.2"
KTX is a set of Kotlin extensions that are commonly used. Check also: https://developer.android.com/kotlin/ktx
Did you define isVisible for a View by yourself?
View class has no method calledisVisible().
As #user2340612 said, it can be defined as:
fun View.isVisible(): Boolean {
return this.visibility == View.VISIBLE
}
There is no isVisible() method inside the class View.
You can define your extension method like this:
fun View.toggleVisibility() {
this.visibility = if (this.visibility == View.VISIBLE) View.INVISIBLE else View.VISIBLE
}
As #Vadim Kotov said, isVisible is not a method that exists within View. There is, however, a getVisibility() function that will return one of the three possible visibility values: VISIBLE, INVISIBLE, or GONE. You can use these results to determine the visibility and set it how you want.

How to change dynamically TextView and ImageView Elements for each Fragment

Background
I am trying to populate fragments' contents through one function. The fragment list changes according to the Navigation Item Selected.
IE: I have 2 Navigation items ("Fruits,Animals") for both, I have 3 categories where the thing that changes is the image and the description, sort of like this:
NavButton>Fruits NavButton>Animals
Apple -> Image and description Alligator -> Image and description
Banana -> Image and description Bat -> Image and description
Cherry -> Image and description Cat -> Image and description
Instead of creating 6 Fragment Layouts and activities, I created 3 and the idea is to clear and set text/images as needed. This way I would be able to save time and memory instead of creating one fragment per activity when the only thing that changes is the text in the textView (already declared in the values) and the image on the imageView (in the drawable section).
Problem
I have not found an implementation to change the textView nor the Imagesrc for ImageView. I have tried per each fragment (which causes FC). I have not found a way to do it for the drawable
Code
Code for the adapter which populates the Tabs
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentPagerAdapter
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import com.company.app.R.id.TextViewFragmentFirst
import com.company.app.R.layout.fragment_fragment_first
import com.company.app.fragments.FragmentFirst
import com.company.app.fragments.FragmentSecond
import kotlinx.android.synthetic.main.fragment_fragment_first.*
class CustomPageAdapter(FragManager:FragmentManager): FragmentPagerAdapter(FragManager) {
//var obj_FragManager = FragManager
var fragManagerItems:ArrayList<Fragment> = ArrayList()
var fragManagerTitles:ArrayList<String> = ArrayList()
var fragmentTxtContents:ArrayList<String> = ArrayList()
var fragmentImgObjs:ArrayList<Int> = ArrayList()
lateinit var textViewToChange:TextView
lateinit var imageViewToChange:ImageView
//findViewById(R.id.TextViewFragmentFirst) as TextView
fun removeFragments()
{
fragManagerItems.clear()
}
fun addFragments(fragmentItem:Fragment,fragmentTitle:String,fragmentTxtContent:String,fragmentImgObj:Int)
{
fragManagerItems.add(fragmentItem)
fragManagerTitles.add(fragmentTitle)
when (fragmentItem){
FragmentFirst()-> print("x == 1") //Here I would like to set textViewToChange & imageViewToChange
FragmentSecond()-> print("x == 2")//Here I would like to set textViewToChange & imageViewToChange
FragmentThird()-> print("x == 3")//Here I would like to set textViewToChange & imageViewToChange
else -> {
print("no valid fragment casted!")
}
}
textViewToChange!!.setText(fragmentTxtContent)
imageViewToChange!!.setImageResource(R.drawable.ic_iconapp) // Here it would need to be based on the fragmentImgObj
}
override fun getItem(position: Int): Fragment {
return fragManagerItems[position]
}
override fun getCount(): Int {
return fragManagerItems.size
}
override fun getPageTitle(position: Int): CharSequence {
return fragManagerTitles[position]
}
}
Fragments are standard, nothing have changed
class FragmentFirst : Fragment() {
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment "
return inflater!!.inflate(R.layout.fragment_fragment_first, container, false)
}
Approaches used
1. I have tried to use import kotlinx.android.synthetic.main.fragment_fragment_first.* along with the textviewID and the setText property within the fragment OnCreateView before the 'return' but only causes a FC. I would like to do it instead on the adapter, however, I ahve not found a way to even set the variables as needed.
Two things.
Consider using a common interface for each fragment since each of one has an image and a description, then no detection and selection of textViewToChange or imageViewToChange will be necessary.
If you are going to be swapping out fragments (removing one and adding another to a View), you will have to create the Fragment dynamically. Removing and adding Fragments that have been defined in an XML resource doesn't work properly.
I found the solution as implement it on the main activity instead of the adapter
import kotlinx.android.synthetic.main.fragment_fragment_first.*
import kotlinx.android.synthetic.main.fragment_fragment_second.*
import kotlinx.android.synthetic.main.fragment_fragment_third.*
...
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here.
objPageAdapter = CustomPageAdapter(supportFragmentManager)
when (item.itemId) {
R.id.nav_fruits -> {
objPageAdapter!!.removeFragments()
objPageAdapter!!.addFragments(FragmentFirst(),getString(R.string.txt_tab_fruits_Element_1))
objPageAdapter!!.addFragments(FragmentSecond(),getString(R.string.txt_tab_fruits_Element_2))
objPageAdapter!!.addFragments(FragmentThird(),getString(R.string.txt_tab_fruits_Element_3))
ViewPagerMain.adapter = objPageAdapter
TabLayoutMain.setupWithViewPager(ViewPagerMain)
this.textViewFragment_1.text = getString(R.string.txt_txtView_fruits_Element_1)
this.textViewFragment_2.text = getString(R.string.txt_txtView_fruits_Element_2)
this.textViewFragment_3.text = getString(R.string.txt_txtView_fruits_Element_3)
...
I assume that you have to wait until all the elements in the tablayout have been populated and you cannot do it in the middle of the tab population since XMLs have not been created.

Categories

Resources