In my app I have a feature, the feature is localise. first, I am using an exposed dropdown menu(using textinputlayout) and this dropdown shows the language list when the user selects the language the app shows the text based on the user's selected language and I save user value in sharedpreference and it's working fine but the problem is when the user closes the app and reopen user can show their selected language text but the dropdown can't change based on sharedpreference value.
MainActivity.kt
class MainActivity : AppCompatActivity() {
companion object {
const val TAG = "MainActivity"
}
lateinit var lanList: List<String>
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
PrefHelper.init(this)
lanList = arrayListOf("EN","AR")
var la = PrefHelper.getValue("localise","")
Log.i("la", "onCreate: $la")
val adapter = MyAdapter(this, android.R.layout.simple_spinner_dropdown_item, lanList)
binding?.typesFilter?.setAdapter(adapter)
binding?.typesFilter.onItemClickListener =
AdapterView.OnItemClickListener { parent, view, position, id ->
val selectedLang: String = parent?.getItemAtPosition(position).toString()
when (selectedLang) {
"EN" -> {
binding.typesFilter.dismissDropDown()
lifecycleScope.launchWhenCreated {
delay(100)
setLocalise("en")
recreate()
}
}
"AR" -> {
binding.typesFilter.dismissDropDown()
lifecycleScope.launchWhenCreated {
delay(100)
setLocalise("ar")
recreate()
}
}
}
}
binding.typesFilter.post {
binding.typesFilter.dismissDropDown()
}
binding?.typesFilter.setDropDownBackgroundDrawable(
ResourcesCompat.getDrawable(
resources,
R.drawable.filter_spinner_dropdown_bg,
null
)
)
}
override fun attachBaseContext(newBase: Context?) {
PrefHelper.init(newBase!!)
super.attachBaseContext(LanguageChangeHelper.setLanguage(newBase!!,PrefHelper.getValue("localise","")!!))
}
private fun setLocalise(lan: String) {
var p:String = PrefHelper.setValue("localise",lan).toString()!!
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/typesFilterContainer"
style="#style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginTop="32dp"
android:background="#drawable/filter_spinner_dropdown_bg"
app:boxBackgroundColor="#color/pastel_orange_light"
app:boxCornerRadiusBottomEnd="20dp"
app:boxCornerRadiusBottomStart="20dp"
app:boxCornerRadiusTopEnd="20dp"
app:boxCornerRadiusTopStart="20dp"
app:boxStrokeWidth="0dp"
app:boxStrokeWidthFocused="0dp"
app:endIconDrawable="#drawable/ic_baseline_keyboard_arrow_down_24"
app:endIconTint="#color/pastel_orange_txt_highlight"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<AutoCompleteTextView
android:id="#+id/typesFilter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#null"
android:dropDownSelector="#drawable/filter_spinner_dropdown_bg"
android:ellipsize="end"
android:inputType="none"
android:maxLines="1"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:singleLine="true"
android:text="EN"
android:textAlignment="center"
android:textColor="#color/pastel_orange_txt_highlight"
tools:ignore="LabelFor">
<requestFocus />
</AutoCompleteTextView>
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:id="#+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:text="#string/title_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/typesFilterContainer" />
<TextView
android:id="#+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="#string/body_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:text="Button"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
MyAdapter.kt
class MyAdapter : ArrayAdapter<Any?> {
constructor(context: Context, resource: Int) : super(context, resource) {}
constructor(context: Context, resource: Int, textViewResourceId: Int) : super(
context,
resource,
textViewResourceId
) {
}
constructor(context: Context, resource: Int, objects: Array<Any?>) : super(
context,
resource,
objects
) {
}
constructor(
context: Context,
resource: Int,
textViewResourceId: Int,
objects: Array<Any?>
) : super(context, resource, textViewResourceId, objects) {
}
constructor(context: Context, resource: Int, objects: List<*>) : super(
context,
resource,
objects
) {
}
constructor(context: Context, resource: Int, textViewResourceId: Int, objects: List<*>) : super(
context,
resource,
textViewResourceId,
objects
) {
}
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults? {
return null
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {}
}
}
}
PrefHelper.kt
object PrefHelper {
private lateinit var prefs: SharedPreferences
private const val PREF_NAME = "PrefHelper"
fun init(context: Context){
prefs = context.getSharedPreferences(PREF_NAME,Context.MODE_PRIVATE)
}
//For String
fun getValue(key:String,value:String):String?{
return prefs.getString(key, value)
}
fun setValue(key:String,value:String){
val prefEditor: SharedPreferences.Editor = prefs.edit()
with(prefEditor){
putString(key,value)
commit()
}
}
}
LanguageChangeHelper.kt
object LanguageChangeHelper {
fun setLanguage(context: Context,lan:String): Context? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
updateResources(context,lan)
} else updateResourcesLegacy(context,lan)
}
#TargetApi(Build.VERSION_CODES.N)
private fun updateResources(context: Context, language: String): Context? {
val locale = Locale(language)
val configuration = context.resources.configuration
val localeList = LocaleList(locale)
LocaleList.setDefault(localeList)
configuration.setLocales(localeList)
return context.createConfigurationContext(configuration)
}
private fun updateResourcesLegacy(context: Context, language: String): Context? {
val locale = Locale(language)
Locale.setDefault(locale)
val resources = context.resources
val configuration = resources.configuration
configuration.locale = locale
resources.updateConfiguration(configuration, resources.displayMetrics)
return context
}
}
better understanding I also show my app
first time open the app
after change the language
when user reopen the app
how can i change user selected option based sharedpreferences?
Thank you
Related
I am trying to make a app that sends messages to a recyclerView from fragment to another using a navgraph, but whenever I go back to my previous fragment to add a new message I lose the data of my recyclerView, and does not pile up.
---This is the kotlin code for the first fragment:
package com.example.passingdata
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import androidx.navigation.Navigation
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
class Fragment_A : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment__a, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val messageET = view.findViewById<EditText>(R.id.ETmessageTaker)
val enterBTN = view.findViewById<Button>(R.id.BTNenter)
enterBTN.setOnClickListener{
val action = Fragment_ADirections.actionFragmentAToFragmentB(messageET.text.toString())
Navigation.findNavController(view).navigate(action)
}
}
companion object {
fun newInstance(param1: String, param2: String) =
Fragment_A().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}
---XML code for first fragment:
<?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"
tools:context=".Fragment_A">
<EditText
android:id="#+id/ETmessageTaker"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:ems="10"
android:hint="Message"
android:inputType="textPersonName"
android:minHeight="48dp"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/BTNenter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Enter"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/ETmessageTaker" />
</androidx.constraintlayout.widget.ConstraintLayout>
---Kotlin code for second fragment :
package com.example.passingdata
import android.content.ContentValues.TAG
import android.os.Bundle
import android.os.Parcelable
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.navigation.Navigation
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.passingdata.databinding.FragmentBBinding
import messageAdapter
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
var state: Parcelable? = null
class Fragment_B : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
private val args:Fragment_BArgs by navArgs()
private var _binding: FragmentBBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentBBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val eachMessage = args.messageRecieved
//putting words in TV
binding.TVNewMessage.text = eachMessage
//putting words in RV
val messageList = mutableListOf(
message(eachMessage)
)
val adapter = messageAdapter(messageList)
binding.RVMessages.adapter = adapter
binding.RVMessages.layoutManager = LinearLayoutManager(context)
binding.BTNBack.setOnClickListener {
Navigation.findNavController(view).navigate(R.id.action_fragment_B_to_fragment_A)
}
}
companion object {
fun newInstance(param1: String, param2: String) =
Fragment_B().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
override fun onResume() {
super.onResume()
Log.d(TAG, "onResume Called")
state = binding.RVMessages.layoutManager?.onSaveInstanceState();
}
override fun onPause() {
super.onPause()
Log.d(TAG, "onPause Called")
state = binding.RVMessages.layoutManager?.onSaveInstanceState();
}
override fun onStop() {
super.onStop()
Log.d(TAG, "onStop Called")
state = binding.RVMessages.layoutManager?.onSaveInstanceState();
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy Called")
_binding = null
}
}
---XML code for second fragment:
<?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"
tools:context=".Fragment_B">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/RV_messages"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="20dp"
app:layout_constraintBottom_toTopOf="#+id/TV_newMessage"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/TV_newMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="60dp"
android:text="TextView"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/BTN_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:layout_marginRight="10dp"
android:text="Back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<Button
android:id="#+id/BTN_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:text="Save"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Someone suggested I override the 3 states and save them like this, but it did not work.
I even tried using SharedPrefrences but it gives me a error saying, "Unresolved reference: getSharedPrefrences".
override fun onResume() {
super.onResume()
Log.d(TAG, "onResume Called")
state = binding.RVMessages.layoutManager?.onSaveInstanceState();
}
override fun onPause() {
super.onPause()
Log.d(TAG, "onPause Called")
state = binding.RVMessages.layoutManager?.onSaveInstanceState();
}
override fun onStop() {
super.onStop()
Log.d(TAG, "onStop Called")
state = binding.RVMessages.layoutManager?.onSaveInstanceState();
}
Its saying adapter is not attached. I am new to kotlin. So I don't know where does it go wrong.
RestaurantModel.kt
package com.example.foodtogo.model
import android.os.Parcel
import android.os.Parcelable
import java.io.Serializable
class RestaurantModel(val name:String?, val address:String?, val delivery_charge: Int, val image: String?, val open: String?,
var menus: List<Menus?>?): Serializable {}
class Menus(val name:String?, val price: Float, val url:String?, var totalInCart: Int):Serializable {}
RestaurantMainActivity.kt
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.foodtogo.databinding.ActivityRestaurantMainBinding
import com.example.foodtogo.model.RestaurantModel
import com.example.foodtogo.view.RestaurantListAdapter
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.*
import com.google.firebase.database.ktx.database
import com.google.firebase.ktx.Firebase
import android.content.Intent as Intent
class RestaurantMainActivity : AppCompatActivity(),RestaurantListAdapter.ValueEventListener {
private lateinit var binding: ActivityRestaurantMainBinding
private lateinit var firebaseAuth: FirebaseAuth
private lateinit var database: FirebaseDatabase
private lateinit var reference: DatabaseReference
private lateinit var restaurantList: ArrayList<RestaurantModel>
//var adapter: RestaurantListAdapter?=null
//private lateinit var restaurantList: MutableList<RestaurantModel?>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityRestaurantMainBinding.inflate(layoutInflater)
setContentView(binding.root)
firebaseAuth = FirebaseAuth.getInstance()
database = FirebaseDatabase.getInstance()
reference = database.reference
Log.e("AKSA", "TEST1")
binding.recyclerViewRestaurant.layoutManager = LinearLayoutManager(this)
Log.e("AKSA", "TEST")
restaurantList = arrayListOf<RestaurantModel>()
getRestaurantData()
Log.e("AKSA", "TEST3")
}
override fun Context.onItemClick(restaurantModel: RestaurantModel) {
val intent = Intent(applicationContext,RestaurantMenuActivity::class.java)
intent.putExtra("RestaurantModel", restaurantModel)
startActivity(intent)
Log.d("AKSA", "MESSAGE")
}
private fun getRestaurantData(){
val db = Firebase.database.reference
val restaurantModelRef = db.child("RestaurantModel")
restaurantModelRef.get().addOnCompleteListener {
if (it.isSuccessful) {
val snapshot = it.result
for (restaurant in snapshot.children) {
Log.d("AKSA", "T4")
val restaurantModel = restaurant.child("RestaurantModel").getValue(RestaurantModel::class.java)
Log.d("AKSA", restaurantModel?.address.toString())
restaurantList.add(restaurantModel!!)
}
val adapter = RestaurantListAdapter(restaurantList, getApplicationContext())
binding.recyclerViewRestaurant.adapter = adapter
adapter.notifyDataSetChanged()
} } }
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menubar, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.home_menu -> {
val intent = Intent(this, ViewOrderActivity::class.java)
startActivity(intent)
}
R.id.signout_menu -> {
firebaseAuth.signOut()
val intent = Intent(this, LOGIN::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
finish()
}
}
return super.onOptionsItemSelected(item)
}
}
activity_restaurant_main.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/white"
tools:context=".RestaurantMainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerViewRestaurant"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="4dp"
android:clipToPadding="false"
android:paddingBottom="2dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
tools:listitem="#layout/recycler_restaurantlist"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
ResaturantListAdapter.kt
import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.foodtogo.R
import com.example.foodtogo.RestaurantMenuActivity
import com.example.foodtogo.model.RestaurantModel
class RestaurantListAdapter(val restaurantList: ArrayList<RestaurantModel>, val clickListener: Context):
RecyclerView.Adapter<RestaurantListAdapter.MyViewHolder>() {
//private lateinit var database: FirebaseDatabase
//private lateinit var reference:DatabaseReference
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): RestaurantListAdapter.MyViewHolder {
val view: View = LayoutInflater.from(parent.context).inflate(R.layout.recycler_restaurantlist,parent,false)
return MyViewHolder(view)
}
override fun onBindViewHolder(holder: RestaurantListAdapter.MyViewHolder, position: Int) {
holder.bind(restaurantList.get(position))
holder.itemView.setOnClickListener{
clickListener.onItemClick(restaurantList.get(position))
}
}
override fun getItemCount(): Int {
return restaurantList.size
}
inner class MyViewHolder(view: View):RecyclerView.ViewHolder(view){
val thumbImage: ImageView =view.findViewById(R.id.thumbImage)
val restaurantName: TextView =view.findViewById(R.id.restaurantName)
val restaurantAddress:TextView=view.findViewById(R.id.restaurantAddress)
val restaurantHours:TextView=view.findViewById(R.id.restaurantHours)
fun bind(restaurantModel: RestaurantModel?){
restaurantName.text=restaurantModel?.name
restaurantAddress.text="Address: "+restaurantModel?.address
restaurantHours.text="Open: "+restaurantModel?.open
Glide.with(this.thumbImage).load(restaurantModel?.image).centerCrop().placeholder(R.drawable.ic_launcher_background).into(thumbImage)
}
}
interface ValueEventListener {
// fun onItemClick(restaurantModel: RestaurantModel)
fun Context.onItemClick(restaurantModel: RestaurantModel)
}
}
private fun Context.onItemClick(restaurantModel: RestaurantModel) {
val intent = Intent(applicationContext, RestaurantMenuActivity::class.java)
intent.putExtra("RestaurantModel", restaurantModel)
startActivity(intent)
}
recycler_restaurantlist.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="wrap_content">
<androidx.cardview.widget.CardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:paddingTop="5dp"
app:cardCornerRadius="7dp"
app:cardElevation="7dp"
app:cardUseCompatPadding="true"
app:contentPadding="5dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/thumbImage"
android:layout_width="110dp"
android:layout_height="110dp"
android:layout_gravity="start"
android:layout_margin="10dp"
tools:srcCompat="#drawable/ic_launcher_background" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="125dp"
android:orientation="vertical">
<TextView
android:id="#+id/restaurantName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:textColor="#color/yellow"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="#+id/restaurantAddress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:textColor="#color/black"
android:textSize="14sp"
android:textStyle="normal" />
<TextView
android:id="#+id/restaurantHours"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:textColor="#color/black"
android:textSize="12sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
While I was using json file it worked. But when I tried to retrieve data from realtime database firebase, it got stuck. I don't know, where does it go wrong. And also I can't retrieve the data from realtime database too.
I've been doing one project on android studio (using kotlin) using fragment. I'm planning to implement a step sensor in another fragment but it didn't work and didn't have error also. I don't know where is the error. The sensor seems good but the steps didn't be counted in the text view. I put the code for the sensor in the fragment class. Anyone can help me? The app didn't crash and didn't tell where is the error just the number of steps didn't be counted
This is the code for Fragment Class
package com.androiddevs.runningappyt.ui.fragments
import android.content.Context.SENSOR_SERVICE
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.androiddevs.runningappyt.R
import com.androiddevs.runningappyt.ui.viewmodels.MainViewModel
import com.androiddevs.runningappyt.ui.viewmodels.AppUtils
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.android.synthetic.main.fragment_steps.*
import java.util.*
import com.androiddevs.runningappyt.core.SharedPreferencesManager
#AndroidEntryPoint
class StepsFragment : Fragment(R.layout.fragment_steps),SensorEventListener
{
private var isStarted = false
private var sensorManager: SensorManager? = null
private var stepCounter = 0
private var counterSteps = 0
private var stepDetector = 0
private var startDate: Date? = null
private var endDate: Date? = null
companion object{
fun newInstance() = StepsFragment()
const val TAG = "StepsFragment"}
private lateinit var viewModel: MainViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_steps, stepsContainer, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)l
sensorManager = context?.getSystemService(SENSOR_SERVICE) as SensorManager
// load previous status if any
SharedPreferencesManager.instance.loadStartDate(startDate)
SharedPreferencesManager.instance.loadInitialStepCount(counterSteps)
Log.d(TAG, "startDate = $startDate")
Log.d(TAG, "counterSteps = $counterSteps")
if (startDate != null) {
isStarted = true
}
initUI()
bindUI()
}
override fun onResume() {
super.onResume()
if (this.isStarted) {
startService()
}
}
override fun onPause() {
super.onPause()
stopService()
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
Log.d(TAG, "accuracy = $accuracy")
}
override fun onSensorChanged(event: SensorEvent) {
when (event.sensor.type) {
Sensor.TYPE_STEP_DETECTOR -> {
stepDetector++
}
Sensor.TYPE_STEP_COUNTER -> {
if (counterSteps < 1) {
counterSteps = event.values[0].toInt()
SharedPreferencesManager.instance.saveInitialStepCount(counterSteps)
}
stepCounter = event.values[0].toInt() - counterSteps
}
}
tv_step_count.text = "$stepCounter"
}
private fun initUI() {
startDate?.let {
tv_start_time.text = getString(R.string.start_time, AppUtils.getFormattedDate(it))
} ?: run {
tv_start_time.text = getString(R.string.start_time, "-")
}
tv_end_time.text = getString(R.string.end_time, "-")
tv_step_count.text = "$stepCounter"
if (this.isStarted) {
btn_start.text = getString(R.string.stop)
} else {
btn_start.text = getString(R.string.start)
}
}
private fun bindUI() {
btn_start.setOnClickListener {
if (this.isStarted) {
stopCounter()
btn_start.text = getString(R.string.start)
} else {
startCounter()
btn_start.text = getString(R.string.stop)
}
}
}
private fun startService() {
val stepsSensor = sensorManager?.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
if (stepsSensor == null) {
Toast.makeText(context, "No Step Counter Sensor !", Toast.LENGTH_SHORT).show()
} else {
sensorManager?.registerListener(this, stepsSensor, SensorManager.SENSOR_DELAY_UI)
}
}
private fun stopService() {
sensorManager?.unregisterListener(this)
}
private fun startCounter() {
isStarted = true
this.stepCounter = 0
this.stepDetector = 0
this.counterSteps = 0
// reset UI
initUI()
startDate = Date()
startDate?.let {
tv_start_time.text =
getString(R.string.start_time, AppUtils.getFormattedDate(it))
SharedPreferencesManager.instance.saveStartDate(it)
}
startService()
}
private fun stopCounter() {
Log.d(TAG, "stopCounter")
isStarted = false
endDate = Date()
endDate?.let {
tv_end_time.text =
getString(R.string.end_time, AppUtils.getFormattedDate(it))
}
stopService()
SharedPreferencesManager.instance.clear()
}}
This is the 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"
tools:context=".ui.MainActivity"
android:id="#+id/stepsContainer">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="50dp"
android:layout_marginEnd="8dp"
android:text="#string/app_name"
android:textSize="40sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="#string/start"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/title" />
<TextView
android:id="#+id/tv_start_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="48dp"
android:layout_marginEnd="8dp"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/btn_start"
tools:text="#string/start_time" />
<TextView
android:id="#+id/tv_end_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="48dp"
android:layout_marginEnd="8dp"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_start_time"
tools:text="#string/end_time" />
<TextView
android:id="#+id/tv_step_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="48dp"
android:layout_marginEnd="8dp"
android:textSize="35sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_end_time"
tools:text="0" />
</androidx.constraintlayout.widget.ConstraintLayout>
the possibility solution is using MutableLiveData().
and how it's works?
MutableLiveData() has observe() method that can be notified on every state change.
see this page to see the example how to implement it
Hello guys i am doing wizard but last activity there is not printing name (String) whats the problem can someone solve it this is xml code of last activity
<?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="wrap_content"
tools:context=".thirdActivity3">
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:layout_marginTop="50dp"
android:textColor="#color/black"
android:text="lala"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:textColor="#color/black"
android:text="lala"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
class thirdActivity3 : AppCompatActivity() {
private lateinit var textView: TextView
private lateinit var textView2: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_third3)
textView = findViewById(R.id.textView)
textView2 = findViewById(R.id.textView2)
val extras = intent.extras
if(extras != null){
textView.text = extras.getString("NAME","") //getString("NAME","")
textView2.text = extras.getInt("AGE",0).toString() //getInt("AGE",0).toString()
}
}
}
and this is activityy codee when i am running age is printing but somehow name string not printing
this is mainActivity where i am transfering name data to second activity with startactivity(intent)
class MainActivity : AppCompatActivity() {
private lateinit var editTextName:EditText
private lateinit var nextButton: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
editTextName=findViewById(R.id.editTextName)
nextButton=findViewById(R.id.nextButton)
nextButton.setOnClickListener {
val name = editTextName.text.toString()
val intent = Intent(this,secondActivity2::class.java)
intent.putExtra("PERONS_NAME",name)
startActivity(intent)
}
}
}
class secondActivity2 : AppCompatActivity() {
private lateinit var inputTextAge:EditText
private lateinit var finishButton: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second2)
inputTextAge=findViewById(R.id.inputTextAge)
finishButton=findViewById(R.id.finishButton)
val extras = intent.extras
var name = ""
if (extras != null){
name=extras.getString("PERSON_NAME","")
}
finishButton.setOnClickListener {
val age = inputTextAge.text.toString().toInt()
val intent = Intent(this,thirdActivity3::class.java)
intent.putExtra("NAME",name)
intent.putExtra("AGE",age)
startActivity(intent)
}
}
}
and this last one is second activity where i am outputing name and transfering to last page thirdactivity. first page code is third activity and problem is that i can read age in activity but name not ouputing
In MainActivity, the KeyName in intent is PERONS_NAME whereas in
SecondActivity2, the KeyName is PERSONS_NAME.
Clearly there is a mismatch of KeyNames.
In order to solve the issue, make sure the KeyName in MainActivity and SecondActivity2 are same.
I'm trying make a spinner with a custom adapter to display images with text like the following
but I got lots of unresolved references so I think I'm doing something terribly wrong
I have two fragments the spinner is inside the second fragment
custome_spinner.xml is the custom layout file
android studio 3.1.2
kotlin_version = '1.2.30'
gradle:3.1.2
customeSpinnerAdapter.kt
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
class customeSpinnerAdapter : BaseAdapter{
override fun getItem(p0: Int): Any {
return flag.length
}
override fun getItemId(p0: Int): Long {
return null
}
override fun getCount(): Int {
return 0
}
val country:String
val flag:String
fun customeSpinnerAdapter(context:Context,name:String,image:String){
this.country = name
this.flag = image
val inflater = LayoutInflater.from(context)
}
override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View {
val view = inflater.inflate(R.layout.custome_spinner)
spinner_image.setImageResource(flag)
spinner_country.setText(country)
return view
}
}
custome_spinner.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/spinner_image"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="5dp"
android:src="#drawable/us" />
<TextView
android:id="#+id/spinner_country"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:layout_gravity="center"
android:text="Custom Text"
android:textColor="#000" />
</LinearLayout>
the widget inside fragment_second.xml
<Spinner
android:id="#+id/spinner"
android:layout_width="368dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/from_textView" />
Your problem lies in customeSpinnerAdapter.kt
customeSpinnerAdapter.kt
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
class customeSpinnerAdapter : BaseAdapter{
override fun getItem(p0: Int): Any {
return flag.length
}
override fun getItemId(p0: Int): Long {
return null
}
override fun getCount(): Int {
return 0
}
val country:String
val flag:String
//Add this
val inflater : LayoutInflater
fun customeSpinnerAdapter(context:Context,name:String,image:String){
this.country = name
this.flag = image
//val inflater = LayoutInflater.from(context)
inflater = LayoutInflater.from(context)
}
override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View {
val view = inflater.inflate(R.layout.custome_spinner)
spinner_image.setImageResource(flag)
spinner_country.setText(country)
return view
}
}