I am using this library, https://github.com/kizitonwose/CalendarView, to create a calendar view. I've followed the docs to add the month header.
I've add the following to res/layout/calendar_month_header_layout.xml:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/headerTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:textSize="26sp"
tools:text="October 2019" />
also added the following to the activity xml:
<com.kizitonwose.calendarview.CalendarView
android:id="#+id/month_header"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cv_dayViewResource="#layout/calendar_day_layout"
app:cv_monthHeaderResource="#layout/calendar_month_header_layout" />
I've also added the following code:
val monthHeader: com.kizitonwose.calendarview.CalendarView = findViewById(R.id.month_header)
monthHeader.monthHeaderBinder = object : MonthHeaderFooterBinder<MonthViewContainer> {
override fun create(view: View) = MonthViewContainer(view)
override fun bind(container: MonthViewContainer, month: CalendarMonth) {
println("TEST")
container.textView.text = "${month.yearMonth.month.name.toLowerCase().capitalize()} ${month.year}"
}
}
However, nothing shows up for the activity. What am I missing? Thank you.
EDIT:
I notice the println("TEST") statement doesn't even get logged
Looks like the problem was I had to have the DayBinder too. The monthHeaderBinder on it's own results in a null error. Below is the working code
val currentMonth = YearMonth.now()
val firstMonth = currentMonth.minusMonths(10)
val lastMonth = currentMonth.plusMonths(10)
val firstDayOfWeek = WeekFields.of(Locale.getDefault()).firstDayOfWeek
setContentView(R.layout.activity_calender_view)
var calendarView: com.kizitonwose.calendarview.CalendarView = findViewById(R.id.calendarView)
calendarView.dayBinder = object : DayBinder<DayViewContainer> {
// Called only when a new container is needed.
override fun create(view: View) = DayViewContainer(view)
// Called every time we need to reuse a container.
override fun bind(container: DayViewContainer, day: CalendarDay) {
container.textView.text = day.date.dayOfMonth.toString()
}
}
calendarView.setup(firstMonth, lastMonth, firstDayOfWeek)
calendarView.scrollToMonth(currentMonth)
calendarView.monthHeaderBinder = object : MonthHeaderFooterBinder<MonthViewContainer> {
override fun create(view: View) = MonthViewContainer(view)
override fun bind(container: MonthViewContainer, month: CalendarMonth) {
container.textView.text = "${month.yearMonth.month.name.toLowerCase().capitalize()} ${month.year}"
}
}
And the activity xml:
<com.kizitonwose.calendarview.CalendarView
android:id="#+id/calendarView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cv_dayViewResource="#layout/calendar_day_layout"
app:cv_monthHeaderResource="#layout/calendar_month_header_layout"/>
Related
I have a VideoView (circle) and custom animation (Falling cards) on the screen, in Fragment, as in the screenshot:
I haven't figured out how to do it any other way, so I've inserted four CardViews, and I'm scrolling through them using AnimationUtils. In code it looks like this:
onViewCreated()
viewLifecycleOwner.lifecycleScope.launch {
// withContext(Dispatchers.Main) {
startAnimation()
// }
}
private var count = 0
private var cardsCount = 0
private var animTime = 0L
private suspend fun startAnimation() {
cardsCount = Utils.getScannerTime3(appsList.size).first
repeatCount = Utils.getScannerTime3(appsList.size).third
val cardsList = arrayListOf(binding.cardAnim, binding.cardAnim2, binding.cardAnim3, binding.cardAnim4)
repeat(repeatCount) {
cardsList.forEach {
if (count < cardsCount) {
cardAnimation(it.animCardView, it.appsName, it.appsIcon, appsList[count])
delay(300)
}
count++
}
}
}
private suspend fun cardAnimation(cardView: CardView, textView: TextView, imageView: ImageView, appInfo: AppInfo) {
val scaleUp = AnimationUtils.loadAnimation(requireActivity(), R.anim.cardview_loader_animation_best)
cardView.startAnimation(scaleUp)
scaleUp.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(p0: Animation?) {
viewLifecycleOwner.lifecycleScope.launch {
withContext(Dispatchers.Main) {
textView.text = Utils.refactorLongAppName(appInfo.appName)
imageView.setImageDrawable(appInfo.appIcon)
// lifecycleScope.launch {
for (i in 0..11) {
cardView.elevation = i.toFloat()
delay(i * 100L)
}
// }
}
}
}
override fun onAnimationEnd(p0: Animation?) {
}
override fun onAnimationRepeat(p0: Animation?) {
}
})
}
I launch VideoView in the standard way in onResume
fun startVideoAnim(view: VideoView, context: Context, resourcesRawId: Int) {
view.setVideoURI(Uri.parse("android.resource://" + context.packageName + "/" + resourcesRawId))
view.setOnPreparedListener {
it.isLooping = true
}
view.requestFocus()
view.start()
}
CardView:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/animCardView"
style="#style/Widget.CardView"
android:layout_width="match_parent"
android:layout_height="54dp"
android:layout_marginHorizontal="24dp"
android:layout_marginVertical="3dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<ImageView
android:id="#+id/appsIcon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginVertical="7dp"
android:layout_marginStart="7dp" />
<TextView
android:id="#+id/appsName"
style="#style/TextStyleBold700"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|start"
android:layout_marginStart="55dp"
android:letterSpacing="0.025"
android:textColor="#color/text_dark"
android:textSize="16sp" />
</androidx.cardview.widget.CardView>
The problem is that the animation does not work as it should, I know that the animation is correct, because if I remove the VideoView completely, everything works as it should. If you simply do not show the video, the animation does not work as it should. I tried to replace VideoView with ExoPlayer and Lottie, although this does not suit me. Unsuccessfully. Please tell me what could be wrong and how to fix it? And if there are tips, ideas on how to make such an animation differently, write too.
I developed an android app that requires 3 cascading dropdownlists using TextInputLayouts and AutoComplete views. I am pulling the data from SQL and thru okhttp I receive the response and I array the results. The problem is that when I select an item from the list, it does not place the selected item in the view. Instead, it is placing some kind of hex string. I did not wire up the other two dropdownlists, so nothing is tied into it.
e.g.: com.testapp.testappmobilekotlin.model.VendorResponse#a3014fb
This is what is displayed when I select an option, "HVAC Supply"
Below is a snippet from the activity. I am assuming that my base adapter and api calls are fine since it is populating the array and the list as designed.
private fun loadVendorList() {
val sharedPreferences: SharedPreferences =
getSharedPreferences("sharedPrefs", Context.MODE_PRIVATE)
val tenantId: String? = sharedPreferences.getString("tenantId_KEY", null)
val token: String? = sharedPreferences.getString("accessToken_KEY", null)
// make API call
val call = checkStockService.getVendorList(tenantId,
"Bearer $token",
tenantId?.toInt(),
"application/json"
)
call.enqueue(object : Callback<VendorResult> {
override fun onResponse(
call: Call<VendorResult>,
response: Response<VendorResult>
) {
if (response.isSuccessful) {
vendorItemsArrayList = response.body()!!.result as ArrayList<VendorResponse>?
// initialize adapter
vendorAdapter = VendorRequestBaseAdapter(
this#CheckStockActivity,
R.layout.dropdown_item,
vendorItemsArrayList
)
val editTextFilledExposedDropdown =
findViewById<AutoCompleteTextView>(R.id.selectVendor)
editTextFilledExposedDropdown.setAdapter(vendorAdapter)
}
}
override fun onFailure(call: Call<VendorResult>, t: Throwable) {
Toast.makeText(this#CheckStockActivity, "error :(", Toast.LENGTH_SHORT).show()
}
})
}
Here is my XML layout where I house the TextInputLayout and AutoCompleteTextView
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/ll_dropdown_search">
<com.google.android.material.textfield.TextInputLayout
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="25dp"
android:layout_marginEnd="25dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<AutoCompleteTextView
android:id="#+id/selectVendor"
android:layout_width="284dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Select Vendor"
android:inputType="none" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
Here is my TextView
<TextView
android:id="#+id/vendorName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:padding="10dp"
android:textColor="#color/black"
android:textStyle="normal"
android:textSize="15sp"
xmlns:android="http://schemas.android.com/apk/res/android"
/>
Below is what happens when I select, let's say, "HVAC Supply" From the list. Any guidance would be more than welcomed! Thanks.
I'm here to answer my own question with the hope that it will help anyone else out there that runs into this problem. Using Kotlin, I realized that I have to set up an "OnItemClickListener" on the AutoCompleteTextView. So, using my model, I coded the following:
val selectVendorDropDown =
findViewById<AutoCompleteTextView>(R.id.selectVendor)
selectVendorDropDown.setAdapter(vendorAdapter)
selectVendorDropDown.onItemClickListener =
AdapterView.OnItemClickListener { parent, view, position, id ->
val selectedItem = parent.adapter.getItem(position) as VendorResponse?
if (selectedItem != null) {
selectVendorDropDown.setText(selectedItem.vendorName)
}
}
This snippet of code, now allows the selected item to be displayed in the textview of whichever view you are using.
Your adapter must have implemented the filterable interface, so you can rewrite convertresulttostring to solve this problem.
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(charSequence: CharSequence): FilterResults {
val charString = charSequence.toString()
val filterResults = FilterResults()
filterResults.values = charString
return filterResults
}
override fun publishResults(
charSequence: CharSequence,
filterResults: FilterResults
) {
}
override fun convertResultToString(resultValue: Any): CharSequence? {
return (resultValue as Selector).Title
}
}
}
I have a button (id: readyButtonIntro) inside a layout (introscreen.xml) that i need to enable. To do that, i have another button inside the RecyclerView.ViewHolder.
This is my Layout to need access
introscreen.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorWhite"
tools:context=".IntroScreenVC">
<LinearLayout
android:id="#+id/indicatorContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent" />
<Button
android:id="#+id/readyButtonIntro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:background="#color/colorWhite"
android:textColor="#color/colorTerciary"
android:alpha="0"
android:enabled="false"
android:text="Ready"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
And the another button is inside into the ViewHolder
slide_item_container.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="15dp"
>
<Button
android:id="#+id/addData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Agregar Datos"
android:background="#drawable/button_rounded2"
/>
</LinearLayout>
How can I enable from inside the class that listener the button?
class IntroSlideViewHolder(view: View) : RecyclerView.ViewHolder(view) {
init {
addData.setOnClickListener(View.OnClickListener {
//NEED TO ENABLE THE BUTTON
// val introScreen = IntroScreenVC()
// introScreen.readyButton()
}
}
I have a fun into IntroScreenVC but always have a error that its null, if a pass the context or view, do nothing.
fun readyButton(){
readyButtonIntro.isEnabled = true
}
Could you help me with this? I would really appreciate it.
Thank you very much!
Regards.
Edit:
I put the adapter and the ViewHolder for more information.
I ignored that because I didn't want to create confusion. Sorry for that..
Class Constructor
data class IntroSlide(val title: String, val description: String, val icon: Int, val firstButton: Boolean, val secondButton: Boolean, val thirdButton: Boolean)
IntroScreenVC.kt
class IntroScreenVC: AppCompatActivity() {
private val introSliderAdapter = IntroScreenAdapter(
listOf(
IntroSlide(
"title1",
"description1",
R.drawable.logo,
false,
false,
false
),
IntroSlide(
"title2",
"description2",
R.drawable.doggrooming,
true,
false,
false
),
IntroSlide(
"title3",
"description3",
R.drawable.introscreen3,
false,
true,
false
)
)
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.introscreen)
introSliderViewPager.adapter = introSliderAdapter
}
}
IntroScreenAdapter.kt
class IntroScreenAdapter(private val introSlides: List<IntroSlide>) : RecyclerView.Adapter<IntroSlideViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): IntroSlideViewHolder {
val layoutInflater = LayoutInflater.from(parent?.context)
val cellForRow = layoutInflater.inflate(R.layout.slide_item_container,parent,false)
return IntroSlideViewHolder(cellForRow)
}
override fun getItemCount(): Int {
return introSlides.size
}
override fun onBindViewHolder(holder: IntroSlideViewHolder, position: Int) {
holder.bind(introSlides[position])
}
}
class IntroSlideViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val textTitle = view.findViewById<TextView>(R.id.textTitle)
private val textDescription = view.findViewById<TextView>(R.id.textDescription)
private val imageIcon = view.findViewById<ImageView>(R.id.imageSlideIcon)
private val addData = view.findViewById<Button>(R.id.addData)
private val addPet = view.findViewById<Button>(R.id.agregarMascota)
val contexto = itemView.context;
fun bind(introSlide: IntroSlide) {
textTitle.text = introSlide.title
textDescription.text = introSlide.description
imageIcon.setImageResource(introSlide.icon)
addData.isEnabled = introSlide.firstButton
addPet.isEnabled = introSlide.thirdButton
}
}
init {
addData.setOnClickListener(View.OnClickListener {
//ADD A ALERTDIALOG AND WHEN PRESS OK NEED TO ENABLE THAT BUTTON
val mDialogView = LayoutInflater.from(contexto).inflate(R.layout.alertdialog_add_data,null)
val builder = AlertDialog.Builder(contexto)
builder.setView(mDialogView)
val dialog: AlertDialog = builder.create()
dialog.show()
dialog.getWindow()?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
mDialogView.agregarDatosOK.setOnClickListener {
//HERE I NEED TO ENABLE THE BUTTON
//readyButtonIntro(introscreen.xml)
}
}
}
Edit2:
This is what I do with sharedPreferences.
IntroScreenAdapter.kt
class IntroSlideViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val textTitle = view.findViewById<TextView>(R.id.textTitle)
private val textDescription = view.findViewById<TextView>(R.id.textDescription)
private val imageIcon = view.findViewById<ImageView>(R.id.imageSlideIcon)
private val addData = view.findViewById<Button>(R.id.addData)
private val addPet = view.findViewById<Button>(R.id.agregarMascota)
//INIT sharedPreferences
private val prefs: SharedPreferences = view.context.getSharedPreferences(getString(R.string.prefs_file), Context.MODE_PRIVATE)
val contexto = itemView.context;
fun bind(introSlide: IntroSlide) {
textTitle.text = introSlide.title
textDescription.text = introSlide.description
imageIcon.setImageResource(introSlide.icon)
addData.isEnabled = introSlide.firstButton
addPet.isEnabled = introSlide.thirdButton
}
}
init {
addData.setOnClickListener(View.OnClickListener {
val mDialogView = LayoutInflater.from(contexto).inflate(R.layout.alertdialog_add_data,null)
val builder = AlertDialog.Builder(contexto)
builder.setView(mDialogView)
val dialog: AlertDialog = builder.create()
dialog.show()
dialog.getWindow()?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
mDialogView.agregarDatosOK.setOnClickListener {
//HERE EDIT THE sharedPreferences
with (prefs.edit()) {
putBoolean("ready_button_enabled", true)
apply()
}
dialog.dismiss()
}
}
}
IntroScreenVC.kt
class IntroScreenVC: AppCompatActivity() {
private val introSliderAdapter = IntroScreenAdapter(
listOf(
IntroSlide(
"title1",
"description1",
R.drawable.logo,
false,
false,
false
),
IntroSlide(
"title2",
"description2",
R.drawable.doggrooming,
true,
false,
false
),
IntroSlide(
"title3",
"description3",
R.drawable.introscreen3,
false,
true,
false
)
)
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.introscreen)
introSliderViewPager.adapter = introSliderAdapter
}
//HERE PUT THE RESUME TO EXPECT THE SHOW AND ENABLE THE BUTTON
override fun onResume() {
super.onResume()
val prefs = getSharedPreferences(getString(R.string.prefs_file), Context.MODE_PRIVATE)
val buttonEnabled = prefs.getBoolean("ready_button_enabled", false)
readyButtonIntro.isEnabled = buttonEnabled
if (buttonEnabled) {
readyButtonIntro.alpha = 1f
}else {
readyButtonIntro.alpha = 0f
}
}
}
SOLUTION:
Into the Activity (IntroScreenVC)
class IntroScreenVC: AppCompatActivity(), IntroScreenAdapter.AdapterOnClick {
private val introSliderAdapter =
listOf(
...
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.introscreen)
introSliderViewPager.adapter = IntroScreenAdapter(introSliderAdapter, this)
}
...
override fun onClick() {
//HERE ENABLE AND SHOW THE BUTTON
readyButtonIntro.isEnabled = true
readyButtonIntro.alpha = 1f
}
And the into the Adapter and RecyclerView
class IntroScreenAdapter(private val introSlides: List<IntroSlide>, val adapterOnClick: AdapterOnClick) : RecyclerView.Adapter<IntroScreenAdapter.IntroSliderViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): IntroScreenAdapter.IntroSliderViewHolder {
val layoutInflater = LayoutInflater.from(parent?.context)
val cellForRow = layoutInflater.inflate(R.layout.slide_item_container,parent,false)
return IntroSliderViewHolder(cellForRow)
}
...
inner class IntroSliderViewHolder(view: View) : RecyclerView.ViewHolder(view) {
...
init {
addData.setOnClickListener(View.OnClickListener {
val mDialogView = LayoutInflater.from(contexto).inflate(R.layout.alertdialog_add_data,null)
val builder = AlertDialog.Builder(contexto)
builder.setView(mDialogView)
val dialog: AlertDialog = builder.create()
dialog.show()
dialog.getWindow()?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
mDialogView.agregarDatosOK.setOnClickListener {
//FINALLY HERE CHANGE THE BUTTON TO ENABLE :)
adapterOnClick.onClick()
}
}
}
}
As I understand your problem you have a class A that is trying to communicate (change something) in class B.
There are several options for solving this kind of problem, depending on your exact needs.
From the code you have provided the relation of your Layouts and classes is not clear enough to me to give a more precise answer.
First of all, I understand you are using a recycler view.
A recycler view can have many items, and I assume you want to be able to enable that button from each item.
In order to let your IntroScreen class communicate with your viewholder, you have to pass a reference to the ViewHolder constructor.
For this purpose you could implement a simple "callback pattern".
Here is an example for defining an interface (e.g. for a function that enables the button) and implementing the callback.
Have a read here to see a well-explained example in Java. In Kotlin you could do it the same way.
Here a summary of the implementation steps:
define interface EnableButtonCallback that implements an abstract method enableButton
let your InfoScreen class implement that interface (in which you enable the button)
pass your InfoScreen class to your RecyclerView adapter and then from your adapter to your ViewHolder
in your ViewHolder onClickListener call the interface method enableButton
Update 2020/08/11
I try to give suggestions based on your updated code.
In the intro screen you set your viewPager adapter, but it is still not clear where this property is coming from and where exactly it is displayed. I guess maybe you just cut out the parameter definition. However, I just assume you have your views set up properly and this is not a problem here. For using recycler view with viewPager I found some related information here.
I can not yet see your use case clearly yet. Are you adding data persistently? Then should your button in the IntroScreen be permanently enabled?
In this case probably SharedPreferences are a good choice for persisting this kind of information. Even when it doesn't need to be persisted. Reading one shared preference file is lightweight and quick enough to be done on the main thread.
I will give you an example implementation here:
Get a shared preferences object
val sharedPref = activity?.getSharedPreferences(
"intro_button_settings_file", Context.MODE_PRIVATE) // String with the key should be in your string resource file
Pass your sharedPref to your adapter and your viewHolder and write to it:
with (sharedPref.edit()) {
putBoolean("ready_button_enabled", true) // String with the key should be in your string resource file
commit()
}
in your IntroScreen check the setting
val readyButtonShouldBeEnabled = sharedPref.getBoolean("ready_button_enabled",
false) // defaults to false
If, after clicking your enable button (that sets the setting to true), you need to return to your IntroScreen activity: then you could enable your button in your activities onResume method
A different solution would be:
You check the setting in your IntroScreen onClick method.
Then you don't need to disable the button.
You just set:
// in your IntroScreen readyButtonIntro onClick method
val buttonEnabled = sharedPref.getBoolean("ready_button_enabled",
false)
if (!buttonEnabled) {
// optional: write a Toast to notify the user why the button is doing nothing (yet)
Toast.makeText(yourIntroScreenContext, "First agregar datos", Toast.LENGTH_SHORT).show()
return // onClick returns, so nothing else will happen when clicked
}
... // your code when the button **should** be enabled
If your button should be disabled again, simply save false to the setting.
Since I do not know more about your use case, this seems like an easy and quick solution to me. This way you do not need to bother with implementing an interface. Anyways, when clicking your button in your viewHolder there is no immediate action taking place in your IntroScreen activity. You still want the user to return to the IntroScreen and click the enabled button.
Then checking if your button was enabled just when clicking on it appears sufficient to me.
I have found a solution and its attached as an answer
I'm currently having trouble populating a layout in a dialog with information from my adapter. The data is fetched from the API and passed into my data class but since the recyclerview that I'm trying to reference is in the Dialog's layout file, not in the file i'm using to call said dialog, the view just returns an null.
Here is my code for context.
CheckboxActivity.kt (Just the callback) people_list is returning null
private val callbackGETUSERS = object : Callback<List<Users>> {
override fun onFailure(call: Call<List<Users>>, t: Throwable) {
Log.e("API-GET-USERS", "Problem GETTING USERS", t) }
override fun onResponse(call: Call<List<Users>>, response: Response<List<Users>>) {
val result = UsersResult(response.body() ?: return run {
Log.e("API-ME", "Problem calling USERS")
})
peopleList = result
people_list.adapter = ManagePeopleAdapter(result)
}
}
d_manage_people.xml (the dialog resource file)
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<TextView
android:id="#+id/manage_people_title"
android:gravity="center"
android:height="24dp"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
style="#style/Subtitle1"
android:text="Create Item"
android:layout_marginBottom="16dp"
android:layout_gravity="center"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/people_list"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</androidx.recyclerview.widget.RecyclerView>
and here is my error
java.lang.IllegalStateException: people_list must not be null
By the way I'm using a plugin that allows me to not use findViewById
Any help would be appreciated :)
You can show dialog after API call. Something like below
private val callbackGETUSERS = object : Callback<List<Users>> {
override fun onFailure(call: Call<List<Users>>, t: Throwable) {
Log.e("API-GET-USERS", "Problem GETTING USERS", t) }
override fun onResponse(call: Call<List<Users>>, response: Response<List<Users>>) {
val result = UsersResult(response.body() ?: return run {
Log.e("API-ME", "Problem calling USERS")
})
peopleList = result
this#CheckboxActivity.showDialog()
}
}
private fun showDialog() {
val dialog = AlertDialog.Builder(this)
val view = layoutInflater.inflate(R.layout.d_manage_people, null)
view.manage_people_title.text = "Manage People"
people_list = view.findById(R.id.people_list)
people_list.adapter = ManagePeopleAdapter(peopleList)
dialog.setView(view)
dialog.show() }
}
And just call API on button click.
onPeopleClicked(view: View) {
dataRetriever.getUsers(callbackGETUSERS, getAuth(), listID)
}
The issue happened to be with me not attaching the view's context
Instead of calling the Recycler View in the CallBack like
people_list
and then setting the adapter from there, I just had the callback call a function that then created the dialog and I used context from that to reach the RecyclerView
val dialog = AlertDialog.Builder(this)
val view = layoutInflater.inflate(R.layout.d_manage_people, null)
dialog.setView(view)
view.manage_people_title.text = "Manage People"
val adapter = ManagePeopleAdapter(result)
view.people_list.adapter = adapter
view.people_list.layoutManager = LinearLayoutManager(this)
I'm trying to add a spinner inside an alert using anko. My code so far looks like this:
alert(getString(R.string.alert)) {
positiveButton("Cool") { toast("Yess!!!") }
customView {
linearLayout {
textView("I'm a text")
padding = dip(16)
orientation = LinearLayout.VERTICAL
spinner(R.style.Widget_AppCompat_Spinner) {
id = R.id.spinner_todo_category
prompt = "Select a Category"
}
}
}
}.show()
but I get compilation errors because apparently that's not how to call a spinner. I've been looking at the docs (Anko GitHub Wiki) but it says nothing about spinners.
Thanks in advance
One solution :
class AddActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val items = listOf(Friend("bla","bla",50),Friend("bla","bla",50));
val adapterFriends = ArrayAdapter(this,R.layout.mon_spinner,items)
verticalLayout {
val friends = spinner { adapter = adapterFriends }
val wine = editText()
button("Say Hello") {
onClick { toast("Hello, ${wine.text}!") }
}
}
}
}
with this layout (mon_spinner.xml) :
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:textSize="14sp"
android:textColor="#color/colorPrimary"
android:spinnerMode="dialog"
android:text="XXX"
/>
It's all right !!
Try this in your AnkoComponent:
spinner {
adapter = ArrayAdapter.createFromResource(
ctx,
R.array.your_string_array,
android.R.layout.simple_spinner_dropdown_item)
}