I'm developing a android app to show some movies in a scrollable view with two columns.
Everything is okay except that I have huge space between rows.
I have tried many things that I found in StackOverflow, like: android:adjustViewBounds="true", set padding to zero and etc.
Can anyone give enlighten me?
Here is how the app is looking like
As you can see there is a huge space between rows
I'm adding the imageViews dynamically through inflate, and I think thats the issue.
Here is my code:
package com.example.androidvidly
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.squareup.picasso.Picasso
import org.json.JSONArray
import org.json.JSONObject
const val MOVIE_OBJECT_ID = "tokenlab.com.MOVIE_OBJECT_ID"
const val MOVIE_OBJECT_VOTES = "tokenlab.com.MOVIE_OBJECT_VOTES"
const val MOVIE_OBJECT_TITLE = "tokenlab.com.MOVIE_OBJECT_TITLE"
const val MOVIE_OBJECT_POSTER_URL = "tokenlab.com.MOVIE_OBJECT_POSTER_URL"
const val MOVIE_OBJECT_RELEASE_DATE = "tokenlab.com.MOVIE_OBJECT_RELEASE_DATE"
const val MOVIE_OBJECT_GENRES = "tokenlab.com.MOVIE_OBJECT_GENRES"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val mQueue = Volley.newRequestQueue(this)
val url = "https://desafio-mobile.nyc3.digitaloceanspaces.com/movies" //API provided
//val url = "http://10.0.2.2:3000"// Node.js Backend
val gallery = findViewById<LinearLayout>(R.id.gallery)
val inflater = LayoutInflater.from(this)
var mAppName = findViewById<TextView>(R.id.appName)
mAppName.text="Vidly"
val gson = Gson()
var request = StringRequest(Request.Method.GET, url, Response.Listener { response ->
var moviesJSONArray = JSONArray(response)
for (i in 0 until moviesJSONArray.length()) {
var e : JSONObject = moviesJSONArray.getJSONObject(i)
//Initializing the object
val arrayStringType = object : TypeToken<ArrayList<String>>() {}.type
var genreListAux:ArrayList<String> = gson.fromJson(e.getString("genres"), arrayStringType)
var movieObject: Movie = Movie(e.getString("id").toInt(), e.getString("vote_average").toDouble(), e.getString("title"), e.getString("poster_url"), genreListAux, e.getString("release_date"))
if (i==0) {
var mImageView = findViewById<ImageView>(R.id.imageDisplay)
mImageView.setTag(movieObject)
loadImageFromUrl(movieObject.poster_url, mImageView)
mImageView.setPadding(0, 0, 0, 0);
}
else if (i==1) {
var mImageView = findViewById<ImageView>(R.id.imageDisplay2)
mImageView.setTag(movieObject)
loadImageFromUrl(movieObject.poster_url, mImageView)
mImageView.setPadding(0, 0, 0, 0);
}
else{
if(i.rem(2)==0) {
var view = inflater.inflate(R.layout.activity_main, gallery, false)
var mImageView = view.findViewById<ImageView>(R.id.imageDisplay)
mImageView.setTag(movieObject)
var height = gallery.height
view.minimumHeight=height
gallery.addView(view)
loadImageFromUrl(movieObject.poster_url, mImageView)
mImageView.setPadding(0, 0, 0, 0);
}
else {
var view = gallery.getChildAt(gallery.childCount-1)
var mImageView = view.findViewById<ImageView>(R.id.imageDisplay2)
mImageView.setTag(movieObject)
loadImageFromUrl(movieObject.poster_url, mImageView)
mImageView.setPadding(0, 0, 0, 0);
}
}
}
}, Response.ErrorListener { error ->
error.printStackTrace()
})
mQueue.add(request)
}
fun showMore(view: View) {
val intent = Intent(this, MovieSelectedActivity::class.java).apply {
var movieObj : Movie = view.getTag() as Movie
putExtra(MOVIE_OBJECT_ID, movieObj.id)
putExtra(MOVIE_OBJECT_GENRES, movieObj.genres)
putExtra(MOVIE_OBJECT_POSTER_URL, movieObj.poster_url)
putExtra(MOVIE_OBJECT_RELEASE_DATE, movieObj.release_date)
putExtra(MOVIE_OBJECT_TITLE, movieObj.title)
putExtra(MOVIE_OBJECT_VOTES, movieObj.vote_average)
}
startActivity(intent)
}
fun loadImageFromUrl(url: String, mImageView: ImageView) {
Picasso.with(this).load(url).placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
.into(
mImageView, null
)
}
}
Here is the xml for the views:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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"
tools:context=".MainActivity">
<LinearLayout
android:id="#+id/gallery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/background"
android:orientation="vertical"
android:weightSum="10"
android:adjustViewBounds="true">
<RelativeLayout
android:layout_weight="2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true">
<TextView
android:id="#+id/appName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textAppearance="#style/TextAppearance.AppCompat.Body2"
android:textColor="#000000"
android:textSize="60dp"
android:adjustViewBounds="true"/>
</RelativeLayout>
<RelativeLayout
android:layout_weight="8"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="1"
android:layout_alignParentLeft="true"
android:adjustViewBounds="true">
<ImageView
android:id="#+id/imageDisplay"
android:layout_width="170dp"
android:layout_height="280dp"
android:clickable="true"
android:onClick="showMore"
android:adjustViewBounds="true"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="1"
android:layout_alignParentRight="true"
android:adjustViewBounds="true">
<ImageView
android:id="#+id/imageDisplay2"
android:layout_width="170dp"
android:layout_height="280dp"
android:clickable="true"
android:onClick="showMore"
android:adjustViewBounds="true"/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</ScrollView>
I Found out that the issue was with the background I was setting in the main linear layout. After removing it the huge spaces disappeared.
android:background="#drawable/background"
Related
I'm having trouble with a Google Maps fragment in my Android app. When I try to use the zoom in/out buttons, it takes me back to the home page instead of zooming in/out. And when I enter an address in the search bar, it doesn't take me to the location I've entered.
I've tried debugging the code and checking the logcat, but I'm not seeing any errors or output related to this issue. I'm using the Google Maps API and have followed the documentation for implementing the zoom and search features.
Here's the relevant code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#004D40"
android:gravity="center_vertical">
<ImageView
android:id="#+id/btnBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:background="#drawable/ic_baseline_arrow_back_24"
android:backgroundTint="#color/white" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:text="Go back to default home page"
android:textColor="#color/white"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar"
android:layout_alignParentBottom="true"
android:layout_marginTop="0dp"
android:layout_marginBottom="04dp">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav"
tools:layout="#layout/fragment_maps" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="end|bottom"
android:padding="16dp">
<Button
android:id="#+id/zoom_in_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/zoom_in"
android:onClick="onZoomIn"
tools:ignore="UsingOnClickInXml" />
<Button
android:id="#+id/zoom_out_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Zoom Out"
android:onClick="onZoomOut"/>
</LinearLayout>
<EditText
android:id="#+id/search_bar"
android:layout_width="326dp"
android:layout_height="39dp"
android:layout_marginStart="10dp"
android:layout_marginTop="12dp"
android:background="#color/white"
android:hint=" Search for a location"
android:imeOptions="actionSearch"
android:inputType="text"
android:maxLines="1"
android:singleLine="true" />
</FrameLayout>
</RelativeLayout>
this is the code for activity_location.xml
package com.developeralamin.bloodapp
import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.location.Geocoder
import android.location.LocationManager
import androidx.fragment.app.Fragment
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.SearchView
import android.widget.Toast
import androidx.core.app.ActivityCompat
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
import java.io.IOException
class MapsFragment : Fragment(), OnMapReadyCallback {
private lateinit var mMap: GoogleMap
private lateinit var searchView: SearchView
private fun onZoomIn(view: View?) {
mMap.animateCamera(CameraUpdateFactory.zoomIn())
}
#SuppressLint("MissingInflatedId")
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_maps, container, false)
// Get the SupportMapFragment and request notification
// when the map is ready to be used.
val mapFragment =
childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
searchView = root.findViewById(R.id.search_bar)
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
Log.d("MapsFragment", "onQueryTextSubmit() called with query = $query")
query?.let { searchLocation(it) }
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
Log.d("MapsFragment", "onQueryTextChange() called with newText = $newText")
return false
}
})
// Add the following functions inside the MapsFragment class
val zoomInButton = root.findViewById<Button>(R.id.zoom_in_button)
zoomInButton.setOnClickListener {
onZoomIn(view)
}
val zoomOutButton = root.findViewById<Button>(R.id.zoom_out_button)
zoomOutButton.setOnClickListener {
mMap.animateCamera(CameraUpdateFactory.zoomOut())
}
return root
}
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
// Enable the My Location layer on the map
if (ActivityCompat.checkSelfPermission(
requireActivity(),
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
requireActivity(),
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return
}
mMap.isMyLocationEnabled = true
mMap.uiSettings.isZoomControlsEnabled = true
mMap.uiSettings.isMyLocationButtonEnabled = true
// Get the user's current location and move the camera
val locationManager = activity?.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
if (location != null) {
val latLng = LatLng(location.latitude, location.longitude)
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f))
}
}
private fun searchLocation(query: String) {
val geocoder = Geocoder(requireContext())
try {
val addresses = geocoder.getFromLocationName(query, 1)
if (addresses != null) {
if (addresses.isNotEmpty()) {
val address = addresses[0]
val latLng = LatLng(address.latitude, address.longitude)
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f))
mMap.addMarker(MarkerOptions().position(latLng).title(query))
Log.d("MapsFragment", "Marker added at $latLng")
} else {
Toast.makeText(requireContext(), "Location not found", Toast.LENGTH_SHORT).show()
}
}
} catch (e: IOException) {
e.printStackTrace()
}
}
}
it is the code for mapsfragement.kt
Any help or suggestions would be greatly appreciated. Thank you!
Hello I am doing a little app for my homework and I want to display data from my php api on the app. But the Recycler View send this message 2022-04-25 00:41:36.662 13593-13593/net.robcorp.finalapp E/RecyclerView: No adapter attached; skipping layout before the adapter code runs because this message 2022-04-25 00:41:36.907 13593-13593/net.robcorp.finalapp I/System.out: [Drivers(pos=1, name=Charles Leclerc, nb=16, points=71, title=Ferrari), Drivers(pos=2, name=Esteban Ocon, nb=31, points=20, title=Alpine)] is displayed after the previous one and is suppose to run just before the adapter.
Here is the DriversFragment.kt:
package net.robcorp.finalapp
import android.content.Context
import android.graphics.Insets.add
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.OneShotPreDrawListener.add
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import net.robcorp.finalapp.R
import net.robcorp.finalapp.databinding.FragmentDriversBinding
import net.robcorp.finalapp.drivers.DriverFragmentAdapter
import net.robcorp.finalapp.drivers.Drivers
import org.json.JSONArray
class DriversFragment : Fragment(R.layout.fragment_drivers) {
private lateinit var recyclerView: RecyclerView
private lateinit var myAdapter: DriverFragmentAdapter;
lateinit var binding: FragmentDriversBinding
private val drivers = ArrayList<Drivers>()
val url = "https://robcorp.net/f1api/getdrivers.php"
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentDriversBinding.inflate(layoutInflater)
recyclerView = binding.driversRecyclerView
recyclerView.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
myAdapter = DriverFragmentAdapter(drivers)
recyclerView.adapter = myAdapter
println("adapter loaded")
downloadDrivers()
}
fun downloadDrivers() {
val task = Volley.newRequestQueue(this.context)
val request = StringRequest(Request.Method.GET, url, {
response ->
val data = response.toString()
val jArray = JSONArray(data)
// Log.e("Error",response.toString())
for (i in 0..jArray.length()-1) {
val json_data = jArray.getJSONObject(i)
// Log.e("Jobject",json_data.toString())
val pos = i+1
val name = json_data.getString("Name")
val nb = json_data.getString("NB")
val points = json_data.getString("Points")
val title = json_data.getString("Title")
val driver = Drivers(pos, name, nb, points, title)
drivers.add(driver)
}
println(drivers)
myAdapter.notifyDataSetChanged()
}, {
error ->
println(error)
})
task.add(request)
}
}
Here is the DriverFragmentAdapter.kt:
package net.robcorp.finalapp.drivers
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import net.robcorp.finalapp.R
import net.robcorp.finalapp.databinding.DriverListBinding
class DriverFragmentAdapter(private var driversList: List<Drivers>): RecyclerView.Adapter<DriverFragmentAdapter.MyViewHolder>() {
class MyViewHolder(val binding: DriverListBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(driver: Drivers) {
val context = itemView.context
val pos = itemView.findViewById<TextView>(R.id.driver_position)
val bar = itemView.findViewById<TextView>(R.id.driver_bar)
val name = itemView.findViewById<TextView>(R.id.driver_name)
val nb = itemView.findViewById<TextView>(R.id.driver_number)
val team = itemView.findViewById<TextView>(R.id.driver_team)
val points = itemView.findViewById<TextView>(R.id.driver_points)
pos.text = driver.pos.toString()
name.text = driver.name
nb.text = driver.nb
team.text = driver.title
points.text = driver.points
if (driver.title == "Ferrari") {
bar.background = ContextCompat.getDrawable(context, R.drawable.ferrari_bar)
} else if (driver.title == "Alpine") {
bar.background = ContextCompat.getDrawable(context, R.drawable.alpine_bar)
} else if (driver.title == "Red Bull") {
bar.background = ContextCompat.getDrawable(context, R.drawable.redbull_bar)
} else if (driver.title == "Mercedes") {
bar.background = ContextCompat.getDrawable(context, R.drawable.mercedes_bar)
} else if (driver.title == "McLaren") {
bar.background = ContextCompat.getDrawable(context, R.drawable.mclaren_bar)
} else if (driver.title == "Alfa Romeo") {
bar.background = ContextCompat.getDrawable(context, R.drawable.alfaromeo_bar)
} else if (driver.title == "AlphaTauri") {
bar.background = ContextCompat.getDrawable(context, R.drawable.alphatauri_bar)
} else if (driver.title == "Williams") {
bar.background = ContextCompat.getDrawable(context, R.drawable.williams_bar)
} else if (driver.title == "Aston Martin") {
bar.background = ContextCompat.getDrawable(context, R.drawable.astonmartin_bar)
} else if (driver.title == "Haas") {
bar.background = ContextCompat.getDrawable(context, R.drawable.haas_bar)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(DriverListBinding.inflate(LayoutInflater.from(parent.context)))
}
override fun getItemCount(): Int {
return driversList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val driver = driversList[position]
holder.binding.apply {
println("je suis dans le binding")
holder.bind(driver)
}
}
fun setDriversList(driversList: List<Drivers>) {
this.driversList = driversList
notifyDataSetChanged()
}
}
fragment_drivers.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=".MainActivity">
<!-- TODO: Update blank fragment layout -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/primary"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginBottom="10dp">
<TextView
android:id="#+id/calendar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="30dp"
android:layout_marginBottom="20dp"
android:fontFamily="#font/marianneb"
android:text="Pilotes"
android:textAlignment="center"
android:textColor="#color/white"
android:textSize="25sp" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/drivers_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="#+id/header"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
driver_list.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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="20dp"
android:elevation="8dp"
android:orientation="horizontal"
android:padding="10dp"
android:background="#drawable/rectangle">
<TextView
android:id="#+id/driver_position"
android:layout_width="30dp"
android:layout_height="match_parent"
android:fontFamily="#font/marianneb"
android:text="1"
android:textColor="#color/black"
android:textSize="25sp"
android:textAlignment="center"/>
<ImageView
android:id="#+id/driver_bar"
android:layout_width="20px"
android:layout_height="match_parent"
android:background="#drawable/ferrari_bar"/>
<LinearLayout
android:layout_width="250dp"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/driver_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fontFamily="#font/marianneb"
android:text="Charles Leclerc"
android:textColor="#color/black"
android:textSize="15sp"
android:layout_marginStart="10dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/driver_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="2.5dp"
android:fontFamily="#font/mariannem"
android:text="16"
android:textColor="#color/black"
android:textSize="10sp" />
<TextView
android:id="#+id/driver_team"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="2.5dp"
android:fontFamily="#font/mariannem"
android:text="Ferrari"
android:textColor="#color/black"
android:textSize="10sp" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="#+id/driver_points"
android:layout_width="50dp"
android:layout_height="match_parent"
android:fontFamily="#font/marianneb"
android:text="578"
android:textColor="#color/black"
android:textSize="25sp"/>
</LinearLayout>
It’s a harmless warning. Since your RecyclerView is already in the layout, it attempts to draw it the moment your view hierarchy becomes visible, sees that there is no adapter assigned, and so it just issues the warning and doesn’t draw it.
Perhaps it would be cleaner to create your adapter (with an empty list) and assign it immediately upon inflating the view, and just update its list when the data is ready.
By the way, it is incorrect to inflate your layout in onCreate. That should be done in onCreateView.
Edit:
Your code here is inflating the layout twice, once for the variable v, and once for the binding property. First of all, there's no reason to inflate it twice. Secondly, since you use v as the return value of onCreateView, anything you do to the views in the binding is pointless and has no effect on the views that are actually on screen.
val v = inflater.inflate(R.layout.fragment_drivers, container, false)
binding = FragmentDriversBinding.inflate(layoutInflater)
// ...
return v
You should only inflate the view once (using the binding) and return the binding's view:
// DELETE THIS LINE: val v = inflater.inflate(R.layout.fragment_drivers, container, false)
binding = FragmentDriversBinding.inflate(layoutInflater)
// ...
return binding.root
Also, it is more proper to set up your views in onViewCreated() instead of in onCreateView(). And if you do that, you actually can move inflation into the super-constructor call by passing the view ID to the Fragment constructor, and then instead of inflating your binding, you bind to the existing view. It would look like this:
class DriversFragment : Fragment(R.layout.fragment_drivers) {
private lateinit var recyclerView: RecyclerView
private lateinit var myAdapter: DriverFragmentAdapter;
lateinit var binding: FragmentDriversBinding
private val drivers = ArrayList<Drivers>()
val url = "https://robcorp.net/f1api/getdrivers.php"
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentDriversBinding.bind(view)
recyclerView = binding.driversRecyclerView
recyclerView.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
myAdapter = DriverFragmentAdapter(drivers)
recyclerView.adapter = myAdapter
println("adapter loaded")
downloadDrivers()
}
//...
}
To add a little bit of clarity to #Tenfour04 's answer.
You can't remove this. They are telling you how to properly inflate it with viewbinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentDriversBinding.inflate(layoutInflater, container, false)
return binding.root
}
also a little side note:
You should destroy your binding like so to prevent memory leaks
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
Now to the question.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//binding = FragmentDriversBinding.bind(view) this is not needed since its already been inflated
//recyclerView = binding.driversRecyclerView why keep recyclerview as another variable when you can access it with binding.driversRecyclerView?
binding.driversRecyclerView.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
myAdapter = DriverFragmentAdapter(drivers)
binding.driversRecyclerView.adapter = myAdapter
println("adapter loaded")
downloadDrivers()
}
Finally the issue is most likely your layout.
Since everything is wrapped inside a linear layout, the constraint layouts position lines don't do anything.
I removed the useless linear layout.
Hopefully this fixes any issues.
sorry about the formatting btw just use CTRL + ALT + L to auto format it
<?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=".MainActivity">
<LinearLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/primary"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginBottom="10dp">
<TextView
android:id="#+id/calendar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="30dp"
android:layout_marginBottom="20dp"
android:fontFamily="#font/marianneb"
android:text="Pilotes"
android:textAlignment="center"
android:textColor="#color/white"
android:textSize="25sp" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/drivers_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="#+id/header"/>
</androidx.constraintlayout.widget.ConstraintLayout>
please help me, I am trying to initialize the simplest recycler view from the stack and it's still resisting.
<?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:minHeight="100dp"
tools:context=".CostInvoiceAttachments">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/CLI_rows_RV"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:itemCount="5"
tools:listitem="#layout/recycler_view_item" />
</androidx.constraintlayout.widget.ConstraintLayout>
item layout
<?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:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:cardUseCompatPadding="true"
app:cardElevation="5dp"
app:cardCornerRadius="2dp"
app:cardPreventCornerOverlap="false">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/CL_Layout_TV"
android:layout_width="match_parent"
android:minHeight="100dp"
android:layout_height="match_parent">
<TextView
android:id="#+id/CL_Size_TV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:text="Size"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#+id/NumberDescription"
app:layout_constraintTop_toBottomOf="#+id/CL_Title_TV" />
<TextView
android:id="#+id/CL_Date_TV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="Date"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/CL_Title_TV" />
<TextView
android:id="#+id/CL_Title_TV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Title"
app:layout_constraintStart_toEndOf="#+id/TitleDescription"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/NumberDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:text="#string/Size_hint"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/TitleDescription" />
<TextView
android:id="#+id/TitleDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="#string/Name_hint"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/DateDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="#string/Date_hint"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/CL_Date_TV"
app:layout_constraintTop_toBottomOf="#+id/CL_Title_TV" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Adapter
package com.platform.adapters;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.platform.R;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class MenuRecAdapter extends RecyclerView.Adapter<RecViewHolder>{
private ArrayList<String> mList = new ArrayList<>();
Activity context;
public MenuRecAdapter(ArrayList<String> mList){
this.mList = mList;
}
public int getItemCount(){
return mList.size();
}
public RecViewHolder onCreateViewHolder(ViewGroup viewGroup, int position){
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.cost_invoice_attachments_item, viewGroup, false);
RecViewHolder pvh = new RecViewHolder(v);
return pvh;
}
public void onBindViewHolder(RecViewHolder holder, int i){
holder.menuTeXT.setText(mList.get(i));
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
}
View holder
package com.platform.adapters;
import android.view.View;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.platform.R;
public class RecViewHolder extends RecyclerView.ViewHolder {
public TextView menuTeXT;
public RecViewHolder(View itemView){
super(itemView);
menuTeXT = (TextView)itemView.findViewById(R.id.CL_Date_TV);
}
}
initialization:
fun initRecyclerView() {
val list: ArrayList<String> = ArrayList()
list.add("something1")
list.add("something2")
val recyclerView = binding.CLIRowsRV
recyclerView.setHasFixedSize(true)
val linearLayoutManager = LinearLayoutManager(applicationContext)
linearLayoutManager.orientation = LinearLayoutManager.VERTICAL
recyclerView.layoutManager = linearLayoutManager
val menuRecAdapter = MenuRecAdapter(list)
recyclerView.setAdapter(menuRecAdapter)
//print(recyclerView.adapter.toString())
}
i give up up i tried evrything this isn't even what i starded with and it still no show no error
i tried adding working recycler from fragment (from the same app) no good won't work
please pretty please help
Edit 1: whole activity
package com.platform
import android.app.PendingIntent.getActivity
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.gson.Gson
import com.platform.adapters.CostInvoicesAttachmentsAdapter
import com.platform.adapters.CostInvoicesRecyclerAdapter
import com.platform.adapters.MenuRecAdapter
import com.platform.api.EmsApi
import com.platform.databinding.ActivityCostInvoiceAttachmentsBinding
import com.platform.pojo.costInvoice.attachments.Attachments
import com.platform.pojo.costInvoices.CostInvoices
import com.platform.utils.ErrorUtil
import dagger.hilt.android.AndroidEntryPoint
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import javax.inject.Inject
#AndroidEntryPoint
class CostInvoiceAttachments : AppCompatActivity() , CostInvoicesAttachmentsAdapter.OnItemClickListener{
#Inject
lateinit var emsApi: EmsApi
#Inject
lateinit var ee : ErrorUtil
var attachments: Attachments=Attachments()
private lateinit var binding: ActivityCostInvoiceAttachmentsBinding
var index: Int =-1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCostInvoiceAttachmentsBinding.inflate(layoutInflater)
setContentView(binding.root)
setContentView(R.layout.activity_cost_invoice_attachments)
index = intent.getIntExtra("index",-1)
initRecyclerView()
//getAttachmentAttachments()
}
/**
* Pobranie załączniki faktury kosztowej
* #author Rafał Pasternak
**/
private fun getAttachmentAttachments() {
val call = emsApi.getCostInvoiceAttachments(
index
)
call.enqueue(object : Callback<ResponseBody> {
override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) =
if (response.isSuccessful) {
var rawJsonString:String? = response.body()?.string()
rawJsonString="{\"Attachments\":"+rawJsonString+"}"
attachments= Gson().fromJson(rawJsonString, Attachments::class.java)
initRecyclerView()
} else {
val errorUtil = ee.parseError(response)
if (errorUtil != null) {
openDialog(errorUtil.message)
} else
openDialog("${resources.getString(R.string.FailedToConnect)} ${response.message()}")
}
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
Log.e("APP", t.localizedMessage)
Log.e("APP", t.message.toString())
}
})
}
/**
* Metoda do wyświetlenia komunikatu użytkownikowi
* #author Rafał Pasternak
**/
fun openDialog(message: String) {
MaterialAlertDialogBuilder(this)
.setTitle(resources.getString(R.string.messageTitle)) //jako res string
.setMessage(message)
.setPositiveButton("OK") { dialog, which ->
}
.show()
}
fun initRecyclerView() {
val list: ArrayList<String> = ArrayList()
list.add("something1")
list.add("something2")
val recyclerView = binding.CLIRowsRV
recyclerView.setHasFixedSize(true)
val linearLayoutManager = LinearLayoutManager(applicationContext)
linearLayoutManager.orientation = LinearLayoutManager.VERTICAL
recyclerView.layoutManager = linearLayoutManager
val menuRecAdapter = MenuRecAdapter(list)
recyclerView.setAdapter(menuRecAdapter)
//print(recyclerView.adapter.toString())
}
/**
* Metoda nadpisująca metodę z interfejsu onItemClickListener
* odsyła do wybranej przez użytkownika umowy
* #author Rafał Pasternak
* **/
override fun onItemClick(position: Int) {
Toast.makeText(this, "Item $position clicked", Toast.LENGTH_SHORT).show()
var index=attachments.attachments[position].id
}
}
The problem looks to be the way how you inflate the binding. You are using 2 setContentView in your Activity which seems to be the last that makes the binding not inflate. Can you try this please:
Remove this code in your activity:
binding = ActivityCostInvoiceAttachmentsBinding.inflate(layoutInflater)
setContentView(binding.root)
setContentView(R.layout.activity_cost_invoice_attachments)
and put this instead:
val binding: ActivityCostInvoiceAttachmentsBinding = DataBindingUtil.setContentView(this, R.layout.activity_cost_invoice_attachments)
This should work. I haven’t tried it but it should work.
Here is a link about How to inflate binding layout into Activity:
https://developer.android.com/topic/libraries/data-binding/expressions#binding_data
The problem is When data refreshes view is not getting updated.
My findings-
1. onCreateview is getting called multiple times, so multiple binder objects are there
2. I checked the list, updated list is reaching to the adapter
3. Data inserted in the db is correct.
4. I have atttached all the code snippets related to this
5. I have used sqaureup library for calendar
package com.universal.best.habittracker.view
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import `androidx.databinding.DataBindingUtil`
import androidx.fragment.app.*
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.universal.best.habittracker.R
import com.universal.best.habittracker.databinding.ActivityMainBinding
import com.universal.best.habittracker.repository.entity.ActivityEntityClass
import com.universal.best.habittracker.view.adapter.ActivityListAdapter
import com.universal.best.habittracker.view.adapter.ActivityStatusAdapter
import com.universal.best.habittracker.viewmodel.MainAcitivityViewModelProvider
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.util.*
class MainActivity() : AppCompatActivity(),
AddActivityFinishInterface, ActivityAdapterEventrack {
lateinit private var mainActivityDataBinding: ActivityMainBinding
lateinit private var viewModel: MainAcitivityViewModelProvider;
val fragmentManager: FragmentManager = supportFragmentManager;
val tag:String="MainActivity"
companion object {
var newFragment: DialogFragment? = null
internal lateinit var context: Context
internal lateinit var mainActivityContext: Context
fun setContext(con: Context, mainActivityContextt: Context) {
context = con
mainActivityContext = mainActivityContextt
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mainActivityDataBinding = DataBindingUtil.setContentView(
this,
R.layout.activity_main
);
setContext(
applicationContext, this
);
viewModel = ViewModelProvider(this).get(MainAcitivityViewModelProvider::class.java)
var handleCLick =
HandleCLick(
this,
fragmentManager, viewModel,
this
);
mainActivityDataBinding.clickHandler = handleCLick;
Log.d(tag,"Adapter created--")
var listAdapter = ActivityListAdapter(this);
Log.d(tag,"Adapter created with Hashcode--"+listAdapter.hashCode())
mainActivityDataBinding.listAdapter = listAdapter;
mainActivityDataBinding.recyclerView.adapter= listAdapter
mainActivityDataBinding.recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL ,false)
var statusAdapter = ActivityStatusAdapter();
mainActivityDataBinding.statusAdaptor = statusAdapter
mainActivityDataBinding.bottomRecylerView.setHasFixedSize(false);
viewModel.retreiveFromDb()
.observe(this, androidx.lifecycle.Observer { list ->
list?.let {
listAdapter.setAdapterData(list)
listAdapter.notifyDataSetChanged()
statusAdapter.setAdapter(list)
statusAdapter.notifyDataSetChanged()
}
})
viewModel.getSaveres()?.observe(this, androidx.lifecycle.Observer { viewModel.retreiveFromDb()
.observe(this, androidx.lifecycle.Observer { list ->
list?.let {
listAdapter.setAdapterData(list)
listAdapter.ListChangedSoCallNotify()
statusAdapter.clear()
statusAdapter.setAdapter(list)
statusAdapter.notifyDataSetChanged()
}
})
})
}
class HandleCLick(
val context: Context,
val fragmentManager: FragmentManager, val viewmodel: MainAcitivityViewModelProvider,
val addActivityFinishInterface: AddActivityFinishInterface
) {
fun onClick(view: View) {
when (view.id) {
R.id.imageView -> {
newFragment =
AddActivityDialogueFragment(
addActivityFinishInterface
)
newFragment?.show(fragmentManager, "dialog")
};
else -> {
Toast.makeText(context, "Invalid Input", Toast.LENGTH_SHORT).show()
};
}
}
}
#Override
override fun clickHandler(activtyName: String, list: ArrayList<Date>?) {
Toast.makeText(this, activtyName, Toast.LENGTH_SHORT).show()
newFragment?.dismiss()
var len: Int = list?.size ?: 0
when {
len == 1 -> {
Toast.makeText(this, "Valid date range selected ", Toast.LENGTH_SHORT)
.show()
list?.let {
viewModel.saveintoDB(activtyName, list.get(0), list.get(len - 1), "0") }
}
else -> Toast.makeText(this, "Valid date range not selected ", Toast.LENGTH_SHORT)
.show()
}
}
#Override
override fun onDestroy() {
super.onDestroy()
viewModel.close();
}
override fun deleteTriggered(model: ActivityEntityClass) {
viewModel.deleteEntityFromDB(model)
}
override fun viewChartTriggered() {
}
override fun imageCharTriggered() {
}
Above is my mainActivity
myAdapterClass
package com.universal.best.habittracker.view.adapter
import android.app.AlertDialog
import android.content.DialogInterface
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.RecyclerView
import com.universal.best.habittracker.R
import com.universal.best.habittracker.databinding.TopActivitiesItemLayoutBinding
import com.universal.best.habittracker.repository.entity.ActivityEntityClass
import com.universal.best.habittracker.view.ActivityAdapterEventrack
import com.universal.best.habittracker.view.MainActivity
import com.universal.best.habittracker.view.MainActivity.Companion.context
import com.universal.best.habittracker.view.MainActivity.Companion.mainActivityContext
class ActivityListAdapter(var adaptercallBackInterface: ActivityAdapterEventrack) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var list: List<ActivityEntityClass>? = null
val tag: String = "ActivityListAdapter"
lateinit var myViewHolder: MyViewHolder
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater =LayoutInflater.from(parent.context)
val databinder = TopActivitiesItemLayoutBinding.inflate(inflater);
Log.d(tag, "onCreate dataBinder--" + databinder.hashCode());
myViewHolder = MyViewHolder(databinder);
Log.d(tag, "onCreate viewholder--" + myViewHolder.hashCode());
var Handler = MyClickHandler(adaptercallBackInterface)
databinder.myclickHanlder = Handler
return myViewHolder;
}
override fun getItemCount(): Int {
return list?.size ?: 0
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
myViewHolder.bindData(list, position);
}
override fun getItemViewType(position: Int): Int {
return position
}
fun setAdapterData(list: List<ActivityEntityClass>?) {
this.list = list
}
class MyViewHolder( databinder: TopActivitiesItemLayoutBinding) :
RecyclerView.ViewHolder(databinder.root) {
val databinderr: TopActivitiesItemLayoutBinding = databinder
fun bindData(
list: List<ActivityEntityClass>?,
i: Int
) {
databinderr.model = list?.get(i)
databinderr.executePendingBindings()
}
}
class MyClickHandler(var eventrack: ActivityAdapterEventrack) {
fun onclick(view: View, entityClass: ActivityEntityClass) {
when (view.id) {
R.id.imageView2 -> {
//open dialogbox and on yes delete it from db..
val dialogClickListener =
DialogInterface.OnClickListener { dialog, which ->
when (which) {
DialogInterface.BUTTON_POSITIVE -> {
Toast.makeText(
MainActivity.mainActivityContext,
"Activity name is ${entityClass.activityName}",
Toast.LENGTH_SHORT
).show()
eventrack.deleteTriggered(entityClass)
}
DialogInterface.BUTTON_NEGATIVE -> {
}
}
}
var builder: AlertDialog.Builder = AlertDialog.Builder(mainActivityContext)
builder.setMessage("Are you sure to delete this activity?")
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener).show()
}
R.id.imageView4 -> {
//open new actiivty with intent
}
}
}
}
fun ListChangedSoCallNotify() {
notifyDataSetChanged()
}
}
mainActivty layout
<?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>
<variable
name="clickHandler"
type="com.universal.best.habittracker.view.MainActivity.HandleCLick" />
<variable
name="listAdapter"
type="com.universal.best.habittracker.view.adapter.ActivityListAdapter" />
<variable
name="statusAdaptor"
type="com.universal.best.habittracker.view.adapter.ActivityStatusAdapter" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/homepage_bg"
tools:context=".view.Activity.MainActivity">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginLeft="40dp"
android:layout_marginTop="48dp"
android:fontFamily="sans-serif-condensed"
android:text="Add New Habit to Track"
android:textColor="#FFFF"
android:textSize="#dimen/_18sdp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/imageView"
android:layout_width="#dimen/_50sdp"
android:layout_height="#dimen/_50sdp"
android:layout_marginTop="28dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:background="#drawable/ic_add"
android:onClick="#{(view)->clickHandler.onClick(view)}"
app:layout_constraintBottom_toBottomOf="#+id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.945"
app:layout_constraintStart_toEndOf="#+id/textView"
app:layout_constraintTop_toTopOf="#+id/textView"
app:layout_constraintVertical_bias="0.738" />
<TextView
android:id="#+id/notext"
android:layout_width="wrap_content"
android:layout_height="23dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView"
tools:text="You are not tracking any habbit" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="72dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/imageView"
tools:listitem="#layout/top_activities_item_layout" />
<TextView
android:id="#+id/textView3"
android:layout_width="149dp"
android:layout_height="24dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="40dp"
android:textColor="#FFFFFF"
android:textSize="#dimen/_18sdp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/recyclerView"
android:text="Habbit Status" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/bottomRecylerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:adapter="#{statusAdaptor}"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView3"
app:layout_constraintVertical_bias="1.0"
tools:listitem="#layout/habit_staus_item" />
<TextView
android:textSize="#dimen/_14sdp"
android:textColor="#FFFF"
android:fontFamily="sans-serif-condensed"
android:id="#+id/textView8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select Other date"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.588"
app:layout_constraintStart_toEndOf="#+id/textView3"
app:layout_constraintTop_toTopOf="#+id/textView3" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
adapter layout
<?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>
<variable
name="model"
type="com.universal.best.habittracker.repository.entity.ActivityEntityClass" />
<variable
name="myclickHanlder"
type="com.universal.best.habittracker.view.adapter.ActivityListAdapter.MyClickHandler" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/itemview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:orientation="vertical"
app:layout_constraintLeft_toLeftOf="parent">
<TextView
android:id="#+id/Yoga"
android:layout_width="123dp"
android:layout_height="174dp"
android:background="#drawable/activity_item_background_color"
android:fontFamily="monospace"
android:gravity="center"
android:text="#{model.activityName}"
android:textColor="#FFFFFF"
android:textSize="#dimen/_30sdp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Yoga" />
<ImageView
android:onClick="#{(view)->myclickHanlder.onclick(view,model)}"
android:id="#+id/imageView2"
android:layout_width="#dimen/_70sdp"
android:layout_height="#dimen/_50sdp"
android:layout_marginTop="12dp"
android:layout_marginEnd="144dp"
android:layout_marginRight="144dp"
app:layout_constraintEnd_toEndOf="#+id/Yoga"
app:layout_constraintHorizontal_bias="0.294"
app:layout_constraintStart_toStartOf="#+id/Yoga"
app:layout_constraintTop_toBottomOf="#+id/Yoga"
app:srcCompat="#drawable/deleete" />
<ImageView
android:onClick="#{(view)->myclickHanlder.onclick(view,model)}"
android:id="#+id/imageView4"
android:layout_width="#dimen/_45sdp"
android:layout_height="#dimen/_45sdp"
android:layout_marginTop="#dimen/_10sdp"
app:layout_constraintEnd_toEndOf="#+id/Yoga"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="#+id/Yoga"
app:layout_constraintTop_toBottomOf="#+id/Yoga"
app:srcCompat="#drawable/chart" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
DataBindingUtil.setContentView() Utility class to create ViewDataBinding from layouts.
Base class for generated data binding classes. If possible, the
generated binding should be instantiated using one of its generated
static bind or inflate methods. If the specific binding is unknown,
bind(View) or inflate(LayoutInflater, int, ViewGroup, boolean) should
be used.
onCreateview() is getting called multiple times
You are using DataBinding. So kindly remove below.
setContentView(R.layout.activity_main)
Finally
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mainActivityDataBinding = DataBindingUtil.setContentView(
this,
R.layout.activity_main
);
The RecyclerView calling inside Alert Dialog, I have tried setting width MATCH_PARENT at run time in onCreateView in adapter class.
if (binding.root.getLayoutParams ().width == RecyclerView.LayoutParams.MATCH_PARENT)
binding.root.getLayoutParams ().width = parent.getWidth ()
Tried calling inside in onCreateView but leaving space vertically. I tried all possible combination which is present on SO but nothing is working.
private fun initDialog() {
if (mAlertDialog == null) {
val mBuilder = AlertDialog.Builder(this)
val view1 = layoutInflater.inflate(R.layout.select_itinerary_dialog, null, false)
val mRecyclerView = view1.findViewById<RecyclerView>(R.id.mRecyclerView)
mRecyclerView?.adapter = SelectItineraryAdapter(this#AddItineraryActivity)
val llm = LinearLayoutManager(this#AddItineraryActivity)
// llm.isAutoMeasureEnabled = false
mRecyclerView?.layoutManager = llm
//mRecyclerView?.layoutManager = LinearLayoutManager(this#AddItineraryActivity)
mCheckBoxSelectAll = view1.findViewById<CheckBox>(R.id.checkSelctAll)
mCheckBoxSelectAll?.setOnCheckedChangeListener { _, b ->
if (!fromBroadcastReceiver) {
for (item in mItinerarylistResponse?.data?.itinerary!!) {
item?.isSelected = b
}
mRecyclerView?.adapter!!.notifyDataSetChanged()
}
fromBroadcastReceiver = false
}
view1.findViewById<AppCompatButton>(R.id.clearItinerary).setOnClickListener {
mAlertDialog!!.dismiss()
}
view1.findViewById<AppCompatButton>(R.id.doneItinerary).setOnClickListener {
try {
for (item in mItinerarylistResponse?.data?.itinerary!!) {
viewContainer.visibility = View.VISIBLE
if (item!!.item == "Wake Up") {
if (item.isSelected) {
wakeUpTimeTV.visibility = View.VISIBLE
wakeUpTimeLay.visibility = View.VISIBLE
} else {
wakeUpTimeTV.visibility = View.GONE
wakeUpTimeLay.visibility = View.GONE }
}
}
} catch (e: Exception) {
}
mAlertDialog!!.dismiss()
}
mBuilder.setView(view1)
mAlertDialog = mBuilder.create()
mAlertDialog?.window?.setBackgroundDrawableResource(android.R.color.transparent)
// mAlertDialog?.setView(view1)
}
}
Adapter
class SelectItineraryAdapter(val contecx: AddItineraryActivity) : RecyclerView.Adapter<SelectItineraryAdapter.MyHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
val binding = DataBindingUtil.inflate<RowItemItinararyBinding>(LayoutInflater.from(contecx), R.layout.row_item_itinarary, parent, false)
// val v= LayoutInflater.from(contecx).inflate(LayoutInflater.from(contecx), R.layout.row_item_itinarary, parent, false)
/* if (binding.root.getLayoutParams ().width == RecyclerView.LayoutParams.MATCH_PARENT)
binding.root.getLayoutParams ().width = parent.getWidth ()*/
val dd = MyHolder(binding)
return dd
}
override fun getItemCount(): Int {
return mItinerarylistResponse?.data?.itinerary!!.size
}
#SuppressLint("ClickableViewAccessibility")
override fun onBindViewHolder(holder: MyHolder, position: Int) {
holder.v.itinararyname.text = mItinerarylistResponse?.data?.itinerary!![position]?.item
holder.v.markReadCheck.setOnCheckedChangeListener { _, isChecked ->
mItinerarylistResponse?.data?.itinerary!![position]!!.isSelected = isChecked
val receiverIntentDetail = Intent()
receiverIntentDetail.action = isitinerarySelected
holder.v.markReadCheck.context.sendBroadcast(receiverIntentDetail)
}
holder.v.detailLat.setOnTouchListener { view, motionEvent ->
when (motionEvent.action) {
MotionEvent.ACTION_DOWN -> {
com.socrpro.utils.error("ACTION_DOWN")
}
MotionEvent.ACTION_UP -> {
// if (itinerary[position].readStatus == 0) {
holder.v.markReadCheck.performClick()
// }
com.socrpro.utils.error("ACTION_UP")
}
MotionEvent.ACTION_MOVE -> {
com.socrpro.utils.error("ACTION_MOVE")
}
}
true
}
holder.v.markReadCheck.isChecked = mItinerarylistResponse?.data?.itinerary!![position]!!.isSelected
}
class MyHolder(val v: RowItemItinararyBinding) : RecyclerView.ViewHolder(v.root)
}
Row_item
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:id="#+id/detailLat" android:layout_width="match_parent" android:layout_height="wrap_content"
android:clickable="true" android:orientation="vertical">
<LinearLayout android:id="#+id/readornot" android:layout_width="match_parent"
android:layout_height="#dimen/_25sdp" android:background="#color/white"
android:gravity="center_vertical" android:orientation="horizontal"
android:paddingTop="#dimen/_5sdp" android:paddingBottom="#dimen/_5sdp">
<CheckBox android:id="#+id/markReadCheck" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:button="#drawable/custom_checkbox" android:layoutDirection="rtl"
android:text="" />
<TextView android:id="#+id/itinararyname" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_gravity="center_vertical"
android:layout_marginStart="#dimen/_2sdp" android:layout_marginEnd="#dimen/_5sdp"
android:layout_weight="1" android:singleLine="true"
android:text="dfgdgfdggfdg" android:textColor="#color/colorPrimary"
android:textSize="#dimen/_10sdp" />
</LinearLayout>
<View android:layout_width="match_parent" android:layout_height=".5dp"
android:layout_alignBottom="#+id/readornot" android:background="#color/linecolorcc" />
</RelativeLayout>
</layout>
Updated.. new option added..*
TL;DR
Replace your vertical LinearLayout (which surrounds the RecyclerView) with a RelativeLayout
Option1 (old answer)
Before surrounding the layout with ScrollView
After adding ScrollView as root
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/search"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/search"
android:orientation="vertical">
<!--Header-->
<LinearLayout
android:id="#+id/static_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/HeaderStyle"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</RelativeLayout>
</ScrollView>
</layout>
The downside of adding ScrollView is that it causes all the surrounded Views to be Scrolled! So try the next option..
Option2 (better one)
Actually, I was not satisfied with Option1 because the header of the table should not disappear when user scrolls down the RecyclerView! So i've tried to replaced the LinearLayout (which surrounds the RecyclerView) with a RelativeLayout and it get the job done..
<?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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/search"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/search">
<!--Header-->
<LinearLayout
android:id="#+id/static_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignStart="#id/rv"
android:layout_alignEnd="#id/rv"
style="#style/HeaderStyle"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/static_header"/>
</RelativeLayout>
</RelativeLayout>
</layout>