ImageView not appearing when button clicked - android

I created a small practice app which changes the image on-screen when the buttonNext is clicked. However, neither the image nor button does anything. Everything in my MainActivity looks normal for an onClickListener setup and I followed various guides to create a layout which works. But, I'm not sure why it looks so weird and does not work in the emulator.
Here is the MainActivity code I wrote so far:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setListener()
}
private fun changeImage(view: View) {
when (view.id) {
R.id.goodMorning -> view.setBackgroundResource(R.drawable.gm1)
R.id.goodMorning -> view.setBackgroundResource(R.drawable.gm2)
else -> view.setBackgroundColor(Color.LTGRAY)
}
}
private fun setListener() {
val goodMorning = findViewById<ImageView>(R.id.goodMorning)
val buttonNext = findViewById<TextView>(R.id.buttonNext)
fun setListener(){
val clickableViews: List<View> =
listOf(goodMorning, buttonNext)
for (item in clickableViews){
item.setOnClickListener() { changeImage(it) }
}
}
}
}
This is the layout xml:
<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"
tools:context=".MainActivity">
<ImageView
android:id="#+id/goodMorning"
android:layout_width="404dp"
android:layout_height="562dp"
android:contentDescription="#android:string/no"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.428"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.365"
tools:srcCompat="#drawable/gm1" />
<Button
android:id="#+id/buttonNext"
style="#style/twoButtons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:text="#string/buttonNext"
android:textSize="#dimen/box_text_size"
app:layout_constraintBaseline_toBaselineOf="#+id/buttonBack"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/buttonBack" />
<Button
android:id="#+id/buttonDownload"
style="#style/twoButtons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:text="#string/buttonDownload"
android:textSize="#dimen/box_text_size"
app:layout_constraintBaseline_toBaselineOf="#+id/buttonBack"
app:layout_constraintEnd_toStartOf="#+id/buttonBack"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/buttonBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:text="#string/buttonBack"
android:textColor="#android:color/black"
android:textSize="#dimen/box_text_size"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/goodMorning"
app:layout_constraintVertical_bias="0.718" />
This is what the app looks like in Pixel 2:
Any help is greatly appreciated!

change the code like this
private fun changeImage(view: View) {
val goodMorning = findViewById<ImageView>(R.id.goodMorning)
when (view.id) {
R.id.buttonBack -> view.setBackgroundResource(R.drawable.gm1)
R.id.buttonNext -> view.setBackgroundResource(R.drawable.gm2)
else -> goodMorning.setBackgroundColor(Color.LTGRAY)
}
}
private fun setListener() {
val buttonNext = findViewById<TextView>(R.id.buttonNext)
val buttonBack = findViewById<TextView>(R.id.buttonBack)
val clickableViews: List<View> =
listOf(buttonBack, buttonNext)
for (item in clickableViews){
item.setOnClickListener() { changeImage(it) }
}
}

I found out how to fix the issue:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val nextButton: Button = findViewById(R.id.buttonNext)
nextButton.setOnClickListener() { changeImage() }
}
private fun changeImage() {
// Shift through all available images
val imageOptions: ImageView = findViewById(R.id.morningImages)
val drawableResources = when (imageOptions) {
buttonNext -> R.drawable.gm1
else -> R.drawable.gm2
}
imageOptions.setImageResource(drawableResources)
// Repeat function needed
}
}
You are better off creating the clickListener at the beginning with onCreate because you will not have to create another private function which can make this issue more confusing than it really is.
Create a new variable within the changeImage function to find the ImageView. After that, make another variable called to create a when block to shift through the images available and end it with an else statement to avoid creating an error.
Set the imageResource to drawableResources so the images appear on-screen when requested.
Note: a repeat function is needed to shift through the images again once the user goes through all of them.

Related

Recyclerview data disappears on scroll

I am trying to fetch the data from Google Spreadsheet and display it in a recyclerView in Kotlin. I could do that without any error but the issue I am facing is when I scroll up or down the data in the recyclerView get disappeared. When I scroll up and then scroll down I can see that all the data that went up is missing and the same with scrolling down. But if I scroll up for more I can see one line of data after every few scrolls.
Another issue I have is with the date that is being displayed. My data in the Google Spreadsheet starts from 01-Jan-2023 (this is how it's shown in the spreadsheet, and without time in it), when it's shown in the recyclerView, all dates are one day earlier. I mean, it shows 31-Dec-2022 for 01-Jan-2023, 01-Jan-2023 for 02-Jan-2023 and so on.
Can somebody help correct my mistakes and improve my code? I have been after this for a couple of days and I couldn't fix the issue.
My code is,
SalesData.kt
class SalesData : AppCompatActivity() {
private lateinit var binding: ActivitySalesDataBinding
#SuppressLint("NotifyDataSetChanged")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySalesDataBinding.inflate(layoutInflater)
setContentView(binding.root)
val salesList = arrayListOf<SalesDataModel>()
val queue = Volley.newRequestQueue(this)
val url = "https://script.google.com/macros/s/AKfsdaffdbghjhfWVM2FeIH3gZY5kAnb6JVeWpg2XeBOZyU6sghhfkuytytg/exec"
val jsonObjectRequest = object: JsonObjectRequest(
Request.Method.GET,url,null,
Response.Listener {
val data = it.getJSONArray("items")
for(i in 0 until data.length()){
val salesJasonObject = data.getJSONObject(i)
val dt = salesJasonObject.getString("Date")
val dateFmt = SimpleDateFormat("yyyy-MM-dd", Locale.US).parse(dt)
val formattedDatesString = dateFmt?.let { it1 -> SimpleDateFormat("dd-MMM-yyyy", Locale.US).format(it1) }
val salesObject = formattedDatesString?.let { it1 ->
SalesDataModel(
// salesJasonObject.getString("Date"),
it1,
salesJasonObject.getString("Branch"),
salesJasonObject.getDouble("NetSale"),
salesJasonObject.getDouble("Profit"),
)
}
if (salesObject != null) {
salesList.add(salesObject)
}
val adapter = SalesDataRecyclerAdapter(this#SalesData,salesList)
binding.rvSalesData.adapter = adapter
binding.rvSalesData.layoutManager = LinearLayoutManager(this#SalesData)
binding.rvSalesData.setHasFixedSize(true)
adapter.notifyDataSetChanged()
}
Toast.makeText(this#SalesData, "Data loaded successfully", Toast.LENGTH_LONG).show()
},Response.ErrorListener {
Toast.makeText(this#SalesData, it.toString(), Toast.LENGTH_LONG).show()
}
){
override fun getHeaders(): MutableMap<String, String> {
return super.getHeaders()
}
}
Toast.makeText(this#SalesData, "Hi", Toast.LENGTH_LONG).show()
queue.add(jsonObjectRequest)
}
}
SalesDataRecyclerAdapter.kt
class SalesDataRecyclerAdapter(
val context: Context,
private val saleDataList:ArrayList<SalesDataModel>
):RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return MyViewHolder(
SalesDataLayoutBinding.inflate(
LayoutInflater.from(parent.context),
parent, false
)
)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val model = saleDataList[position]
if (holder is MyViewHolder){
holder.binding.tvSales.text = model.salesAmount.toString()
holder.binding.tvBranch.text = model.branch
holder.binding.tvDate.text = model.date
holder.binding.tvProfit.text = model.profit.toString()
}
}
override fun getItemCount(): Int {
return saleDataList.size
}
class MyViewHolder(val binding: SalesDataLayoutBinding) : RecyclerView.ViewHolder(binding.root)
}
activity_sales_data.xml
<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/white"
tools:context=".SalesData">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<!--
<androidx.core.widget.ContentLoadingProgressBar
android:id="#+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/new_green"
android:padding="10dp"
android:text="SALES DATA"
android:textColor="#color/white"
android:textSize="24sp"
android:layout_gravity="bottom|end"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvSalesData"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
sales_data_layout.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/tvDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="Date"
android:layout_weight="1"/>
<TextView
android:id="#+id/tvBranch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="Branch"
android:layout_weight="1"/>
<TextView
android:id="#+id/tvSales"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="Sales"
android:layout_weight="1"/>
<TextView
android:id="#+id/tvProfit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="Profit"
android:layout_weight="1"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Since your root view in sales_data_layout.xml has the size:
android:layout_width="match_parent"
android:layout_height="match_parent"
Each item will take up the whole parent area, which in your case will end up with each individual item taking up the whole screen, and thus needing multiple scrolls to see the next item. You probably want to change the height to wrap_content for the root view, to see more items on the screen at once.
Add a comparator that tells the recylcer view exactly when to redraw.
class WordsComparator : DiffUtil.ItemCallback<Word>() {
override fun areItemsTheSame(oldItem: Word, newItem: Word): Boolean {
//=== here doesn't work for complex objects
// simple high-speed code goes here it is called over and over
// my app the same item has the same id easy compare
return (oldItem._id == newItem._id)
}
override fun areContentsTheSame(oldItem: Word, newItem: Word): Boolean { // you developer have to compare the contents of complex objects
// you need high speed code here for best results
// if possible don't call any functions that could do other
// unecessary things.
// compare the contents of the complex items.
return (oldItem._id == newItem._id
&& oldItem.checked == newItem.checked
&& oldItem.word == newItem.word
&& oldItem.color == newItem.color
&& oldItem.recolor == newItem.recolor
&& oldItem.rechecked == newItem.rechecked)
}
}

How to change the text on the second activity on button clicked from first activity? [KOTLIN]

I have to implement OTP validation on my application, I just want to get the mobile number from the previous activity and set it to the textview on the next activity once I clicked the Next Button intent from Activity 1 to Activity 2.
Here is how it looks like in view:
I would like to put the mobile number below the please enter the otp that has sent to..
First try: I called the ObjectSingleton.mobileNum since it carries the mobile # then I used mobileNum.setText(ObjectSingleton.mobileNum) but it ddint work.
My codes in 1st Activity where intent is happening to go to the next Activity;
class MobileNumberActivity : AppCompatActivity(), OtpInterface.MobileNumberViews {
lateinit var presenterMobileNumber:MobileNumberPresenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_mobile_number)
presenterMobileNumber = MobileNumberPresenter()
presenterMobileNumber.mobileViews = this
close_icon2.setOnClickListener {
finish()
}
nxtBtn.setOnClickListener {
if (inputText.text.isNullOrEmpty()) {
inputText.error = "Please enter valid mobile number."
} else if (inputText.text.toString().length != 10) {
inputText.error = "Please enter valid mobile number."
} else{
val mobile = inputText.text.toString()
presenterMobileNumber.otpMobile(mobile)
}
}
}
override fun ifFailed(msg: String) {
errorMsg.setText(msg)
}
override fun ifSuccess(res: OtpData) {
errorMsg.setText("Sent!")
var intent = Intent(this, OtpValidationActivity::class.java)
startActivity(intent)
}
Here are the codes of the 2nd Acitivy where I want to change the text of mobile number display
class OtpValidationActivity : AppCompatActivity(), OtpValidateInterface.OtpValidateViews {
lateinit var otpPresenter: OtpPresenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_otp_verification)
otpPresenter = OtpPresenter()
otpPresenter.otpValidationViews = this
verifyOtpBtn.setOnClickListener {
if (otp_input.text.isNullOrEmpty()) {
otp_input.error = "Please enter OTP."
} else{
val otpNumber = otp_input.text.toString()
otpPresenter.otpValidate(ObjectSingleton.mobileNum,otpNumber)
}
}
}
override fun validateFailed(res: String) {
resend.setText("Failed")
}
override fun validateSuccess(msg: OtpValidationData) {
resend.setText("Success")
}
For your REFERENCE here's the XML file of the said PICTURE above where should I put the Mobile number.
<?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"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/rectangle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="#+id/linearLayout6"
android:layout_width="372dp"
android:layout_height="wrap_content"
android:background="#drawable/otpbg"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.487"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.041">
<LinearLayout
android:id="#+id/linearLayout5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/_30sdp"
android:text="OTP VERIFICATION"
android:textColor="#color/reply_black_800"
android:textSize="#dimen/_22sdp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</TextView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Please enter the OTP that has sent to">
</TextView>
<TextView
android:id="#+id/mobileNum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/_22sdp"
android:layout_marginBottom="#dimen/_30sdp"
android:text="#string/_63"
android:textColor="#color/colorPrimary"
android:textSize="#dimen/_19sdp"
android:textStyle="bold">
</TextView>
</LinearLayout>
<com.mukesh.OtpView
android:id="#+id/otp_input"
android:layout_width="267dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:layout_marginLeft="#dimen/_10sdp"
android:layout_marginRight="#dimen/_10sdp"
android:inputType="number"
android:textAppearance="?attr/textAppearanceHeadline5"
android:textColor="#android:color/black"
app:OtpItemCount="6"
app:OtpItemWidth="#dimen/_30sdp"
app:OtpLineColor="#color/reply_black_800"
app:OtpViewType="line" />
<TextView
android:id="#+id/resend"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/_19sdp"
android:gravity="center"
android:textSize="#dimen/_14sdp"
android:text="#string/didn_t_recieve_the_code_resend_code"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/otp_view"
app:layout_constraintVertical_bias="0.039"
android:paddingBottom="#dimen/_30sdp"/>
</LinearLayout>
<androidx.appcompat.widget.AppCompatButton
android:id="#+id/verifyOtpBtn"
android:layout_width="378dp"
android:layout_height="42dp"
android:background="#drawable/radius_btn"
android:backgroundTint="#color/colorPrimary"
android:text="Next"
android:textAllCaps="false"
android:textColor="#color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.484"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/linearLayout6"
app:layout_constraintVertical_bias="0.117" />
</androidx.constraintlayout.widget.ConstraintLayout>
I am new to Kotlin/Android Develepment I hope someone help me with this.
#JUniorDEV
UPDATE: Imma share to you my MobileNumberPresenter codes:
var mobileViews:OtpInterface.MobileNumberViews? = null
override fun otpMobile(mobile: String) {
Fuel.post("https://api.staging.riderko.com/riderko_be/public/api/riderSendRegisterOtp", listOf(
"mobile" to mobile
)).timeout(5000)
.header("Accept", "application/json")
.responseObject<OtpResponse>{request, response, result ->
when (result) {
is Result.Failure -> {
mobileViews?.ifFailed(result.error.response.statusCode.toString())
}
is Result.Success -> {
val (bytes, error) = result
if (bytes != null) {
val status = bytes.success
if (status){
mobileViews?.ifSuccess(bytes.data)
}else{
mobileViews?.ifFailed(bytes.message)
}
}
}
}
}
}
in OtpInterface.MobileNumberViews
add second parameter as string to ifSuccess
in MobileNumberPresenter
change mobileViews?.ifSuccess(bytes.data) to mobileViews?.ifSuccess(bytes.data, mobile)
and you ifSuccess method will be changed to
override fun ifSuccess(res: OtpData, mobileNum: String) {
errorMsg.setText("Sent!")
var intent = Intent(this, OtpValidationActivity::class.java)
intent.putExtra("MOBILE_NUMBER",mobileNum)
startActivity(intent)
}
And in OtpValidationActivity
val mobileNum = arguments?.getString("MOBILE_NUMBER")
Update the code of 1st activity to
override fun ifSuccess(res: OtpData) {
errorMsg.setText("Sent!")
var intent = Intent(this, OtpValidationActivity::class.java)
startActivity(intent)
intent.putExtra("MobileNum",mobile)
}
Now in the second activity after setContentView(R.layout.activity_otp_verification)
add this line:
val MobNo = intent.getExtra("MobileNum")
mobileNum.text = MobNo
Hope this will work
Here in the MobileNumberActivity inside the ifSuccess() before you do startActivity(intent) do intent.putExtra("IDENTIFER",mobileNum)
Now in the 2nd activity simply do val mobNO = intent.getStringExtra("IDENTIFER")
and now assign the mobNo to the desired textView.
This helps pass data between activities.
I was able to solve this simply by calling ObjectSingleton.mobNum assigned to a variable and displayed it into view I just learnt that once objectsingleton has been assigned to, the value will be carried over to any part of your app, this value will be removed automatically when you close your app.

Spinner not showing list of options from list of strings

I'm trying to make a spinner with list of locale months (or string in general). I already checked a few tutorials on this topic and had this running using string-array and ArrayAdapter.createFromResource() but i need to also show dynamic things like filtered list of years etc.
My activity:
class ChartActivity : AppCompatActivity() {
private val view by lazy { ActivityChartBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setSpinners()
setContentView(R.layout.activity_chart)
}
private fun setSpinners() {
setMonthSpinner()
}
private fun setMonthSpinner() {
var months = DateFormatSymbols.getInstance().shortMonths
var monthsAdapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, months)
monthsAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
view.spinnerMonth.adapter = monthsAdapter
}
}
activity xml:
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Spinner
android:id="#+id/spinnerMonth"
android:spinnerMode="dropdown"
android:layout_width="match_parent"
android:layout_height="32dp"
android:layout_weight="1"
android:gravity="center" />
<View
android:id="#+id/divider"
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="?android:attr/listDivider" />
<Spinner
android:id="#+id/spinnerYear"
android:spinnerMode="dropdown"
android:layout_width="match_parent"
android:layout_height="32dp"
android:layout_weight="1"
android:gravity="center" />
</LinearLayout>
Spinners (without values) are visible in emulator, click on them triggers visual effects, but doesn't show value list
Because you're not using your inflated binding in setContentView you're setting the layout again setContentView(R.layout.activity_chart) but you're updating view using view.spinnerMonth. This won't have effect.
So the correct way would be set setContentView(view.root).
So your activity would look like this:
class MainActivity : AppCompatActivity() {
private val view by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(view.root)
setSpinners()
}
private fun setSpinners() {
setMonthSpinner()
}
private fun setMonthSpinner() {
var months = DateFormatSymbols.getInstance().shortMonths
var monthsAdapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, months)
monthsAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
view.spinnerMonth.adapter = monthsAdapter
}
}

BottomSheet is jumping on button clicks

I have a BottomSheet which houses a product detail card. The problem is, when I click on the + or - button on the product detail while the bottom sheet is in it's Expanded state, it jumps down.
When it is down and I click on the buttons it doesn't jump, it only happens when it is in it's Expanded (completely up) state
I have attached a GIF to show what is exactly happening
Here is the code
scan_sheet.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:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:animateLayoutChanges="false"
android:background="#drawable/bottom_sheet_dialog_fragment"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="100dp"
app:layout_behavior="studio.monotype.storedemo.BottomSheetBehavior">
<include
layout="#layout/hero_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/divider_view"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_marginStart="24dp"
android:layout_marginTop="44dp"
android:layout_marginEnd="24dp"
android:background="#color/colorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/hero_item" />
<include
layout="#layout/related_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#+id/divider_view"
tools:layout_editor_absoluteX="0dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
ScanActivity.kt (simplified to show only what is essential)
class ScanActivity : AppCompatActivity() {
private lateinit var bottomSheet: BottomSheetBehavior<*>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_scan)
setupBottomSheet()
showSheet()
}
private fun setupBottomSheet() {
bottomSheet = BottomSheetBehavior.from(bottom_sheet)
bottomSheet.isHideable = true
bottomSheet.skipCollapsed= true
bottomSheet.isDraggable = true
bottomSheet.state = BottomSheetBehavior.STATE_HIDDEN
bottomSheet.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback {
override fun onSlide(bottomSheet: View, slideOffset: Float) {
}
#SuppressLint("SwitchIntDef")
override fun onStateChanged(sheet: View, newState: Int) {
when (newState) {
BottomSheetBehavior.STATE_HIDDEN -> {
codeScanner.startPreview()
}
}
}
})
plus_btn.setOnClickListener {
var qty= qty_tv.text.toString().toInt()
qty++
qty_tv.text =qty.toString()
}
minus_btn.setOnClickListener {
var qty= qty_tv.text.toString().toInt()
if(qty!=0)
{
qty--
}
qty_tv.text =qty.toString()
}
}
private fun showSheet() {
bottomSheet.state = BottomSheetBehavior.STATE_EXPANDED
}
}
it seems that google engineer gave correct answer
Seems like something is going on because you are setting
android:layout_gravity="bottom" on the view with the
BottomSheetBehavior. You should remove that line.
It helped on my case
Looks to me like that could be a bug in the BottomSheetBehavior? Seems like the height of the sheet isn't getting saved or restored correctly. After the button is pressed, a layout happens again which changes the height. Could you file a bug at https://issuetracker.google.com/issues/new?component=439535

DSL-like OnClick-listener for a custom view using kotlin in Android

I'm trying to create an DSL-like OnClick-listener (in kotlin) for a custom view that I'm using several places in the Android project I'm currently working on. The view has an ImageView, a primary textview and a secondary textview. I'm trying to create a listener-helper that allows you to only override specific methods of an interface instead of all of them (inspired by this article). But I can't get it working. Actually it doesn't even work using regular OnClick listeners.
Here's my ErrorMessageView:
class ErrorMessageView #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0,
defStyleRes: Int = 0
) : FrameLayout(context, attrs, defStyle, defStyleRes) {
private var mOnClickListener: OnErrorMessageViewClickListener? = null
init {
LayoutInflater.from(context).inflate(
R.layout.custom_errorview,
this,
true)
ButterKnife.bind(this)
}
interface OnErrorMessageViewClickListener {
fun onImageClick()
fun onPrimaryTextClick()
fun onSecondaryTextClick()
}
... left out for brevity ...
fun setOnErrorMessageViewClickListener(
onViewClickListener: OnErrorMessageViewClickListener?) {
this.mOnClickListener = onViewClickListener
}
fun setOnErrorMessageViewClickListener(init: ErrorMessageViewClickListenerHelper.() -> Unit) {
val listener = ErrorMessageViewClickListenerHelper()
listener.init()
mOnClickListener = listener
}
#OnClick(R.id.image_container)
internal fun onImageViewClick() {
Timber.d("Clicked image view")
mOnClickListener?.onImageClick()
}
#OnClick(R.id.primary_text_container)
internal fun onPrimaryTextViewClick() {
Timber.d("Clicked primary textview")
mOnClickListener?.onPrimaryTextClick()
}
#OnClick(R.id.secondary_text_container)
internal fun onSecondaryTextViewClick() {
Timber.d("Clicked secondary textview")
mOnClickListener?.onSecondaryTextClick()
}
}
And here's my helper class:
private typealias ErrorViewClickListener = () -> Unit
open class ErrorMessageViewClickListenerHelper : ErrorMessageView.OnErrorMessageViewClickListener {
private var mImageClick: ErrorViewClickListener? = null
fun onImageClick(onImageClick: ErrorViewClickListener?) {
mImageClick = onImageClick
}
override fun onImageClick() {
mImageClick?..invoke()
}
private var mPrimaryTextClick: ErrorViewClickListener? = null
fun onPrimaryTextClick(onPrimaryTextClick: ErrorViewClickListener?) {
mPrimaryTextClick = onPrimaryTextClick
}
override fun onPrimaryTextClick() {
mPrimaryTextClick?.invoke()
}
private var mSecondaryTextClick: ErrorViewClickListener? = null
fun onSecondaryTextClick(onSecondaryTextClick: ErrorViewClickListener?) {
mSecondaryTextClick = onSecondaryTextClick
}
override fun onSecondaryTextClick() {
mSecondaryTextClick?.invoke()
}
}
My layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp">
<android.support.v7.widget.AppCompatImageView
android:id="#+id/image_container"
android:layout_width="#dimen/dialog_worklist_image_size"
android:layout_height="#dimen/dialog_worklist_image_size"
android:layout_centerVertical="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="ContentDescription" />
<TextView
android:id="#+id/primary_text_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginEnd="24dp"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:textSize="16sp"
android:clickable="true"
android:focusable="true"
app:layout_constraintEnd_toEndOf="#+id/image_container"
app:layout_constraintStart_toStartOf="#+id/image_container"
app:layout_constraintTop_toBottomOf="#id/image_container" />
<TextView
android:id="#+id/secondary_text_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginEnd="24dp"
android:layout_marginStart="24dp"
android:textSize="16sp"
android:clickable="true"
android:focusable="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/primary_text_container" />
</android.support.constraint.ConstraintLayout>
I'm using the helper in my code like this, but nothing gets logged (It's almost as if no clicklistener can be attached):
override fun setWorklistNotEnabledMessage(showMessage: Boolean) {
if (showMessage) {
mView?.dialog_worklist_recyclerview?.visibility = View.GONE
mView?.dialog_worklist_errorview?.apply {
visibility = View.VISIBLE
setSecondaryTextClickListener(View.OnClickListener { Timber.d("Test secondary click") })
setErrorDrawable(R.drawable.ic_worklist_disabled_black_24dp)
setPrimaryText(R.string.global_worklist_disabled_error)
setSecondaryText(R.string.dialog_worklist_worklist_disabled_error_secondary_text)
setOnErrorMessageViewClickListener {
onSecondaryTextClick { Timber.d("Test secondary click") }
onPrimaryTextClick { Timber.d("Test primary click") }
onImageClick { Timber.d("Test image click") }
// . this#WorklistDialog
}
}
} else {
mView?.dialog_worklist_errorview?.apply {
visibility = View.GONE
setErrorDrawable(null)
setPrimaryText("")
setSecondaryText("")
setOnErrorMessageViewClickListener(null)
}
}
}
Does anyone have a suggestion to what is wrong with my code?
Btw. the above code is used in a DialogFragment - that is why you might notice the mView?. as a bit awkward. But that is the way to get a handle on the views in a dialog.
Was just about to start crying when I finally found the solution - OMG.
The problem was the SwipeRefreshLayout in the layout file for the dialogfragment, which can be seen here:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/dialog_worklist_toolbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="#color/colorPrimary"
android:elevation="4dp"
android:minHeight="?android:attr/actionBarSize"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<com.conhea.smartgfr.ui.examination.layouts.ErrorMessageView
android:id="#+id/dialog_worklist_errorview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/dialog_worklist_toolbar" />
<ProgressBar
android:id="#+id/dialog_worklist_progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/dialog_worklist_toolbar" />
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/dialog_worklist_swiperefreshlayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
app:layout_constraintTop_toBottomOf="#id/dialog_worklist_toolbar">
<android.support.v7.widget.RecyclerView
android:id="#+id/dialog_worklist_recyclerview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent" />
</android.support.v4.widget.SwipeRefreshLayout>
</android.support.constraint.ConstraintLayout>
The SwipeRefreshLayout was blocking the custom ErrorMessageView from being clickable.
After adding mView?.dialog_worklist_swiperefreshlayout?.isEnabled = false to the below in my DialogFragment everything started working:
override fun setWorklistNotEnabledMessage(showMessage: Boolean) {
if (showMessage) {
mView?.dialog_worklist_recyclerview?.visibility = View.GONE
mView?.dialog_worklist_swiperefreshlayout?.isEnabled = false
mView?.dialog_worklist_errorview?.apply {
visibility = View.VISIBLE
setErrorDrawable(R.drawable.ic_worklist_disabled_black_24dp)
setPrimaryText(R.string.global_worklist_disabled_error)
setSecondaryText(R.string.dialog_worklist_worklist_disabled_error_secondary_text)
setOnErrorMessageViewClickListener {
onSecondaryTextClick { Timber.d("Test secondary click") }
onPrimaryTextClick { Timber.d("Test primary click") }
onImageClick { Timber.d("Test image click") }
}
}
} else {
mView?.dialog_worklist_errorview?.apply {
visibility = View.GONE
setErrorDrawable(null)
setPrimaryText("")
setSecondaryText("")
setOnErrorMessageViewClickListener(null)
}
}
}

Categories

Resources