E/RecyclerView: No adapter attached; skipping layout. Recyclerlist can't be viewed. Output get crashed - android-layout

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.

Related

Saving RecyclerView state in a fragment when exiting it

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();
}

Android Studio Recycler View have gaps between the rows. Help me fix

I followed this tutorial on youtube for my school project. The app is able to display selected images from gallery but the recycler view have gaps in every row. What do I code to fix this app? help. enter image description here
here's my activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
android:scrollbarStyle="insideInset"
android:scrollbars="vertical"
tools:context=".MainActivity">
<Button
android:id="#+id/pick"
android:layout_width="53dp"
android:layout_height="64dp"
android:layout_margin="12dp"
android:layout_weight="0"
android:backgroundTint="#FF5722"
android:text="+"
android:textSize="24sp"
app:cornerRadius="64dp" />
<TextView
android:id="#+id/totalPhotos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:gravity="center"
android:textColor="#FFFFFF" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView_Gallery_Images"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_weight="1"
</LinearLayout>
RecyclerAdapter.java
package com.example.mygram;
import android.media.Image;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private ArrayList<Uri> uriArrayList;
public RecyclerAdapter(ArrayList<Uri> uriArrayList) {
this.uriArrayList = uriArrayList;
}
#NonNull
#Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.custom_single_image,parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerAdapter.ViewHolder holder, int position) {
holder.imageView.setImageURI(uriArrayList.get(position));
}
#Override
public int getItemCount() {
return uriArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.image);
}
}
}
Custom single images.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
xmlns:tools="http://schemas.android.com/tools">
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scaleType="centerCrop"
app:layout_constraintDimensionRatio="1"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
And here's the MainActivity.java
package com.example.mygram;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
TextView textView;
Button pick;
ArrayList <Uri> uri = new ArrayList<>();
RecyclerAdapter adapter ;
private static final int Read_Permission = 101;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.totalPhotos);
recyclerView = findViewById(R.id.recyclerView_Gallery_Images);
pick = findViewById(R.id.pick);
adapter = new RecyclerAdapter(uri);
recyclerView.setLayoutManager(new GridLayoutManager(MainActivity.this,3));
recyclerView.setAdapter(adapter);
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, Read_Permission);
}
pick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setType("image/*");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 1);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1 && resultCode == Activity.RESULT_OK){
if(data.getClipData() !=null) {
int x = data.getClipData().getItemCount();
for (int i = 0; i < x; i++) {
uri.add(data.getClipData().getItemAt(i).getUri());
}
adapter.notifyDataSetChanged();
textView.setText("Photos ("+uri.size()+")");
}else if (data.getData()!=null){
String imageURL=data.getData().getPath();
uri.add(Uri.parse(imageURL));
}
}
}
}
The concept of the app is instagram feed tester. I want to be able to display images like the grid in instagram but the gap is appearing preventing it to happen. help me please thankyou
In your Custom single images.xml replace the height of the parent layout to wrap_content. Replace your code with the following
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scaleType="centerCrop"
app:layout_constraintDimensionRatio="1"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
Everything is right : Just need to Change this to this: (images.xml)
android:layout_height="match_parent"
to
android:layout_height="wrap_content"
in your model xml file

How can i set sharedpreferences update value in dropdown menu

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

Step sensor doesn't count in the textview (in fragment)

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

create a custom spinner adapter in android using kotlin

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
}
}

Resources