overriding onNavigationItemSelected stops navigation component functionality of opening fragments on item click, instead it calls onNavigationItemSelected and nothing else happens.
navigation view setup called in on create
private fun setupNavigationDrawer(){
NavigationUI.setupWithNavController(binding.navigationView,navHostFragment.findNavController())
binding.navigationView.setNavigationItemSelectedListener(this)
}
activity
class MainActivity : AppCompatActivity(),NavigationView.OnNavigationItemSelectedListener
onNavigationItemSelected
override fun onNavigationItemSelected(item: MenuItem): Boolean {
if(binding.mainActivityRootView.isDrawerOpen(GravityCompat.END)){
binding.mainActivityRootView.closeDrawer(GravityCompat.END)
}
else if(binding.mainActivityRootView.isDrawerOpen(GravityCompat.START)){
binding.mainActivityRootView.closeDrawer(GravityCompat.START)
}
return true
}
Navigation view xml
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:menu="#menu/menu_home_navigation_drawer"
android:paddingStart="15dp"
android:paddingEnd="15dp"
app:headerLayout="#layout/layout_navigation_drawer_header"
app:itemIconTint="#color/lipstick"
android:layout_gravity="end"
app:drawerLayoutCornerSize="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" >
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="bottom"
android:layout_marginBottom="40dp"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_main_blue"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="#color/lipstick" />
<TextView
android:id="#+id/textView41"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/montserratmedium"
android:text="Version IMPLEMENT"
android:textColor="#color/pinkish_grey"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.navigation.NavigationView>
i have set menu item id as navigation fragment id and it works without the onNavigationItemSelected being set i also have navigation view below fragment container in xml
i tried to
-change return value onNavigationItemSelected
-setting up onNavigationItemSelected listener before setupWithNavController which results in the listener not getting called at all
In the end i solved it by manually opening fragments
from
override fun onNavigationItemSelected(item: MenuItem): Boolean {
if(binding.mainActivityRootView.isDrawerOpen(GravityCompat.END)){
binding.mainActivityRootView.closeDrawer(GravityCompat.END)
}
else if(binding.mainActivityRootView.isDrawerOpen(GravityCompat.START)){
binding.mainActivityRootView.closeDrawer(GravityCompat.START)
}
return true
}
to
override fun onNavigationItemSelected(item: MenuItem): Boolean {
if(binding.mainActivityRootView.isDrawerOpen(GravityCompat.END)){
binding.mainActivityRootView.closeDrawer(GravityCompat.END)
}
else if(binding.mainActivityRootView.isDrawerOpen(GravityCompat.START)){
binding.mainActivityRootView.closeDrawer(GravityCompat.START)
}
when(item.itemId){
else ->{
NavigationUI.onNavDestinationSelected(item,navHostFragment.findNavController())
}
}
return true
}
Related
I'm opening this discussion because I need help for a school project.
At the moment, I have a scrollable activity with some buttons, everything is built like this:
a constraint layout, with SearchView, ScrollView and a BottomNavigationBar, and inside the ScrollView there's a LinearLayout with all my buttons.
Here is the full xml file:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<SearchView
android:id="#+id/BarraRicerca"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="10dp"
android:gravity="top"
android:iconifiedByDefault="false"
android:imeOptions="actionDone"
android:queryHint="Cerca un tutorial"
android:labelFor="#id/BarraRicerca"
android:suggestionRowLayout="#color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ScrollView
android:id="#+id/scrollView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_weight="1"
android:fillViewport="false"
android:orientation="vertical"
android:padding="10dp"
android:layout_marginTop="60dp"
app:layout_constraintBottom_toTopOf="#id/BottomBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/BarraRicerca">
<LinearLayout
android:id="#+id/Linearlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.Flipper.FlipperList">
<Button
android:id="#+id/FlintstonesF"
android:layout_width="300dp"
android:layout_height="49dp"
android:layout_gravity="center_horizontal"
android:layout_margin="100dp"
android:text="Flintstones" />
<Button
android:id="#+id/tutorial2"
android:layout_width="300dp"
android:layout_height="49dp"
android:layout_gravity="center_horizontal"
android:layout_margin="200dp"
android:layout_weight="1"
android:text="ciao" />
<Button
android:id="#+id/tutorial3"
android:layout_width="300dp"
android:layout_height="49dp"
android:layout_gravity="center_horizontal"
android:layout_margin="100dp"
android:layout_weight="1"
android:text="hello" />
</LinearLayout>
</ScrollView>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/BottomBar"
android:layout_width="0dp"
android:layout_height="60dp"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:layout_gravity="bottom"
android:background="?android:attr/windowBackground"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
and the result is this, everything works
Now I need to implement the SearchView to actually search through my buttons, For example if I search Flintstones (or Flint, or Fli etc.) I want the Flintstones button to be the only one shown. The same goes for "ciao" and so on, I will obviously have more buttons than these.
I tried every possible solution I found on the internet but nothing seems to work. This is my code
package com.example.Flipper
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import com.example.pinballacademy.R
class FlipperList : AppCompatActivity() {
val passaFlintstones: Button get() = findViewById(R.id.FlintstonesF)
val bottone2: Button get() = findViewById(R.id.tutorial2)
val bottone3: Button get() = findViewById(R.id.tutorial3)
val searchbar: SearchView get() = findViewById(R.id.BarraRicerca)
val linLay: LinearLayout get() = findViewById(R.id.Linearlayout)
var listaFlipper: ArrayList<String> = ArrayList()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_flipper_list)
/* listaFlipper.clear();
listaFlipper.add(passaFlintstones.text.toString())
listaFlipper.add(bottone2.text.toString())
listaFlipper.add(bottone3.text.toString())*/
searchbar.isSubmitButtonEnabled=true
searchbar.setOnQueryTextListener() {
fun onQueryTextChange(newText: String?): Boolean {
filter(newText)
return true
}
fun onQueryTextSubmit(query: String?): Boolean {
filter(query)
return true
}
// Do your task here
}
passaFlintstones.setOnClickListener()
{
val intent = Intent(this, FlintstonesScheda::class.java)
//avvia registrazione
startActivity(intent)
// finish()
}
}
fun filter(searchText: String?) {
for (i in 0 until linLay.childCount) {
val button: Button = linLay.getChildAt(i) as Button
if (button.text.toString().contains(searchText!!)) {
button.isVisible=true
} else button.isVisible=false
}
}
private fun SearchView.setOnQueryTextListener(function: () -> Unit) {
}
}
As you can see I'm not even near to a solution, I hope you can help! Thank you!
I have already created a custom layout for badge counter and on inflating menu my cart icon is not working my codes are below.
cart Item Layout
<FrameLayout
style="?attr/actionButtonStyle"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:background="?attr/selectableItemBackground"
android:clipToPadding="false"
android:focusable="true">
<ImageView
android:id="#+id/badge_icon_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="#drawable/ic_cart"/>
<TextView
android:id="#+id/cart_badge_text_view"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="right|end|top"
android:layout_marginEnd="-5dp"
android:layout_marginRight="-5dp"
android:layout_marginTop="3dp"
android:background="#drawable/badge_cart_bg"
android:gravity="center"
android:padding="3dp"
android:textColor="#android:color/white"
android:text="0"
android:textSize="10sp"/>
toolbar menu
<item android:id="#+id/cart"
android:title=""
app:showAsAction="always"
app:actionLayout="#layout/custom_cart_item_layout"
android:icon="#drawable/ic_cart"/>
Code in fragment
code
Try this once-
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
...
myToolbar.inflateMenu(R.menu.sample_menu)
myToolbar.setOnMenuItemClickListener {
when (it.itemId) {
R.id.action_settings -> {
// Navigate to settings screen
true
}
R.id.action_done -> {
// Save profile changes
true
}
else -> false
}
}
}
}
for more details please find official link
In the onCreate of your fragment, enable options menu by calling
setHasOptionsMenu(true)
Do this in the fragment's oncreate not in the parent activity
I have made an app in Android Studio which imports data from a website...when I open the app the card views in which the data is to be imported are empty and get loaded after some time. I wanted to know if there is any way in which I can cover it up so that till the time it is being loaded my splash screen stays there. Here is a video showing the lag:
Card View loading time lag
Edit: Here is the movie Adapter:
class MoviesAdapter(
private var movies: MutableList<Movie>,
private val onMovieClick: (movie: Movie) -> Unit,
) : RecyclerView.Adapter<MoviesAdapter.MovieViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
val view = LayoutInflater
.from(parent.context)
.inflate(R.layout.item_movie, parent, false)
return MovieViewHolder(view)
}
override fun getItemCount(): Int = movies.size
override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
holder.bind(movies[position])
}
fun appendMovies(movies: List<Movie>) {
this.movies.addAll(movies)
notifyItemRangeInserted(
this.movies.size,
movies.size - 1
)
}
inner class MovieViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val poster: ImageView = itemView.findViewById(R.id.item_movie_poster)
fun bind(movie: Movie) {
itemView.setOnClickListener { onMovieClick.invoke(movie) }
Glide.with(itemView)
.load("https://image.tmdb.org/t/p/w342${movie.posterPath}")
.transform(CenterCrop())
.into(poster)
}
}
}
My main_activity_xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg_gradient"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="16dp"
android:text="#string/discover"
android:textColor="#android:color/white"
android:textSize="45sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="#string/popular"
android:textColor="#android:color/white"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="#string/most_popular_movies" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/popular_movies"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="#string/top_rated"
android:textColor="#android:color/white"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="#string/highest_rated_movies" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/top_rated_movies"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="#string/upcoming"
android:textColor="#android:color/white"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="#string/stay_updated" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/upcoming_movies"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="16dp"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="#string/now_playing"
android:textColor="#android:color/white"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="#string/now_in_Cinemas" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/now_playing_movies"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="10dp"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
Api Key:
interface Api {
#GET("movie/popular")
fun getPopularMovies(
#Query("api_key") apiKey: String =
"eff7d87eb14cdf1fb273414692d3e3a8",
#Query("page") page: Int,
): Call<GetMoviesResponse>
}
Api Loader:
api.getPopularMovies(page = page)
.enqueue(object : Callback<GetMoviesResponse> {
override fun onResponse(
call: Call<GetMoviesResponse>,
response: Response<GetMoviesResponse>,
) {
if (response.isSuccessful) {
val responseBody = response.body()
if (responseBody != null) {
onSuccess.invoke(responseBody.movies)
} else {
onError.invoke()
}
} else {
onError.invoke()
}
}
override fun onFailure(call: Call<GetMoviesResponse>, t:
Throwable) {
onError.invoke()
}
})
Is there anything else that I should specify?
without code it's hard to answer the question, but you could always use a ViewSwitcher that displays a "Loading" state before the data for the cardviews are ready, but holds the space, so the UI won't jump, and then have the Card view displayed once the data is loaded.
Could be something like:
sealed class CardData {
object Loading: CardData()
class Info(val items: List<CardInfo>): CardData()
}
fun loadData() {
viewModel.cardData.observe { cardData ->
when(cardData) {
is Loading -> {
binding.switcher.displayedChild = 0
}
is Info -> {
binding.switcher.displayedChild = 1
binding.listOfCards.items = cardData.items
}
}
}
for your specific case:
// display the loading view before making the call
binding.switcher.displayedChild = 0
api.getPopularMovies(page = page)
.enqueue(object : Callback<GetMoviesResponse> {
override fun onResponse(
call: Call<GetMoviesResponse>,
response: Response<GetMoviesResponse>,
) {
if (response.isSuccessful) {
val responseBody = response.body()
if (responseBody != null) {
onSuccess.invoke(responseBody.movies)
} else {
onError.invoke()
}
} else {
onError.invoke()
}
}
override fun onFailure(call: Call<GetMoviesResponse>, t:
Throwable) {
onError.invoke()
}
})
// in your onSuccess()
private void onSuccess(List<Movies> movies) {
binding.switcher.displayedChild = 1
listAdapter.items = movies
listAdapter.notifyDatasetChanged()
}
// in your onError()
private void onError() {
binding.switcher.displayedChild = 2 // you can add a third child for errors
}
then the XML would be something like (missing attributes):
<ViewSwitcher
android:id="#+id/switcher">
<!-- child 0 - loading state -->
<ProgressBar
android:id="#+id/loader"
/>
<!-- child 1 - movies state -->
<RecyclerView
android:id="#+id/movies"
/>
<!-- child 2 - error state -->
<TextView
android:id="#id/error_text"
/>
</ViewSwitcher>
If you want to wait in the splash screen, you will need to make that request in the splash screen.
When you have a successful response, you then navigate and pass the data through args/intent extras, assuming this is a different fragment/activity.
Then, when you are setting creating the list adapter you just need to pass this list through the constructor and set wire everything up, like you probably already have.
Hope it helps, but let me know if this wasn't clear enough!
You can create a Splash screen view exactly like your splash screen in your main activity and show it first while loading all the data from the network in the background, once the data arrives, hide this splash screen view and show app's main screen.
You can instead use shimmer effect to show data loading in background.
So I'm fairly new to Kotlin.
I am trying to create an onClickListener on an image button to open the share interface, so that the particular video from the recyclerView can be shared via SMS, etc.
I followed various tutorials on how to do this as I am trying to execute this within a fragment, and the app just keeps crashing when I try to open the fragment in question.
I get the following error
java.lang.ClassCastException: java.lang.Integer cannot be cast to android.widget.ImageButton
Here is what my fragment code looks like:
SearchFragment.kt
class SearchFragment : Fragment(), View.OnClickListener
{
private var layoutManager: RecyclerView.LayoutManager? = null
private var adapter: RecyclerView.Adapter<ClipAdapter.ViewHolder>? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View
{
val rootView = inflater.inflate(R.layout.fragment_search, container, false)
loadData()
return rootView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{
val shareBtn = view.findViewById<ImageButton>(R.id.button_to_share)
shareBtn.setOnClickListener(this)
}
private fun loadData()
{
val service = TwitchServiceBuilder.buildService(TwitchService::class.java)
val requestCall = service.getClips("anerdfails")
requestCall.enqueue(object : Callback<List<Clip>>
{
override fun onResponse(
call: Call<List<Clip>>,
response: Response<List<Clip>>
)
{
if (response.isSuccessful)
{
//process data
recyclerView.layoutManager = GridLayoutManager(activity, 2)
recyclerView.adapter = ClipAdapter(response.body()!!)
} else
{
//output alert
AlertDialog.Builder(activity!!)
.setTitle("API error")
.setMessage("Response, but something went wrong ${response.message()}")
.setPositiveButton(android.R.string.ok) { _, _ -> }
.setIcon(android.R.drawable.ic_dialog_alert)
.show()
}
}
override fun onFailure(call: Call<List<Clip>>, t: Throwable)
{
//process failure
AlertDialog.Builder(activity!!)
.setTitle("API error")
.setMessage("No response, and something went wrong $t")
.setPositiveButton(android.R.string.ok) { _, _ -> }
.setIcon(android.R.drawable.ic_dialog_alert)
.show()
}
})
}
override fun onClick(v: View?)
{
Toast.makeText(activity, "Its toast!", Toast.LENGTH_SHORT).show()
}
}
And here are my 2 layouts for the RecyclerView:
fragment_search.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:paddingStart="15dp"
android:paddingTop="?attr/actionBarSize"
android:paddingEnd="15dp"
tools:context=".ui.search.SearchFragment">
<androidx.appcompat.widget.SearchView
android:background="#drawable/search_bar"
android:id="#+id/clipSearch"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="5dp"
android:focusable="true"
android:focusableInTouchMode="true"
app:layout_constraintBottom_toTopOf="#+id/recyclerView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="75dp"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/clipSearch" />
</androidx.constraintlayout.widget.ConstraintLayout>
clip_layout.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"
tools:context=".ui.search.SearchFragment">
<VideoView
android:id="#+id/videoClip"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
app:layout_constraintDimensionRatio="w,2:3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/txtTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/videoClip"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/txtChannel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/txtTitle"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/txtGame"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/txtChannel"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/txtViews"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/txtGame"
tools:ignore="HardcodedText" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="30dp"
android:orientation="horizontal"
android:weightSum="2"
android:layout_marginTop="15dp"
app:layout_constraintTop_toBottomOf="#+id/txtViews">
<ImageButton
android:id="#+id/favouriteButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#null"
android:scaleType="fitCenter"
android:src="#drawable/ic_baseline_favorite_border_24" />
<ImageButton
android:id="#+id/button_to_share"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#null"
android:scaleType="fitCenter"
android:src="#drawable/ic_baseline_share_24" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Seems like a simple mistake on my part, but I'm pulling my hair out trying to work out what I've done wrong to cause the error on loading.
Any help would be appreciated.
I see you're trying to find the button "ShareBtn" inside the fragment which is totally wrong.
the "ShareBtn" doesn't belong to the fragment, it belongs to the viewHolder which you have created inside "ClipAdapter"
What you need to do is creating an interface inside "ClipAdapter" and create an object from it inside the Adapter
then call the method which is should the clickListener delegates the click to it
lastly, you should implement it inside the fragment and put whatever logic you want
This link will help you implement it
You are casting ID of view which is an Integer to ImageButton which is a View in this line
val shareBtn = R.id.button_to_share as ImageButton
You should use this instead
val shareBtn = findViewById<ImageButton>(R.id.button_to_share)
UPDATE
Also you should find views after fragment view got created. It means you should call `findViewById` inside `onViewCreated` and not inside `onCreateView`. If you try to find views before view of fragment gets created then you get `NullPointerException` since there is no view yet.
I'm trying to hide part of my view in recycler when user toggles switch.
But when i toggle switch, sometimes it behaves in a strange way and hides only part of my view. It happens every 4 switch clicks (show-hide-show-hide), and i can't manage to solve this bug. Any advices what am i doing wrong?
There are screenshots of properly displayed view and awkwardly hidden view. As you can see, at the second screenshot seekbar with 2 image views is not fully hidden.
UPDATED: The problem is solved. Problem was in include tag. It somehow works wrong, the same layout in item file works fine.
Here is code for hiding logic:
itemView.light_switch.setOnCheckedChangeListener { _, isChecked ->
itemView.brightness.visibility = if (isChecked) View.VISIBLE else View.GONE
lightCallback(lamp, isChecked)
}
And here is my layout (recycler item):
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:background="#1a1a1a">
<ImageView
android:id="#+id/light_icon_image_view"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/prod_foot" />
<TextView
android:id="#+id/light_name_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginStart="8dp"
android:fontFamily="sans-serif-medium"
android:textColor="#ffffff"
android:textSize="16sp"
android:textStyle="normal"
app:layout_constraintBottom_toBottomOf="#+id/light_icon_image_view"
app:layout_constraintStart_toEndOf="#+id/light_icon_image_view"
app:layout_constraintTop_toTopOf="#+id/light_icon_image_view"
tools:text="Floodlight 24 368 (01)" />
<TextView
android:id="#+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:text="No group"
android:textColor="#7fffffff"
android:textSize="14sp"
android:textStyle="normal"
app:layout_constraintStart_toStartOf="#+id/light_name_text_view"
app:layout_constraintTop_toBottomOf="#+id/light_name_text_view" />
<android.support.v7.widget.SwitchCompat
android:id="#+id/light_switch"
style="#style/SwitchCompatStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="#+id/light_icon_image_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#+id/light_icon_image_view"
app:thumbTint="#android:color/white" />
<include
android:id="#+id/brightness"
layout="#layout/brightness_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/light_icon_image_view">
</include>
<ImageView
android:id="#+id/light_gradient_circle"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_marginTop="40dp"
app:layout_constraintStart_toStartOf="#+id/light_icon_image_view"
app:layout_constraintTop_toTopOf="#+id/light_icon_image_view"
app:srcCompat="#drawable/badge_color_wheel_active_block" />
</android.support.constraint.ConstraintLayout>
Include layout is provided below (seekbar with 2 images):
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="#1a1a1a"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imageView"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginStart="16dp"
app:layout_constraintBottom_toBottomOf="#+id/seekbar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/seekbar"
app:srcCompat="#drawable/ic_dim_min" />
<SeekBar
android:id="#+id/seekbar"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="11dp"
android:layout_marginStart="11dp"
android:layout_marginTop="8dp"
android:max="255"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/imageView2"
app:layout_constraintStart_toEndOf="#+id/imageView"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
app:layout_constraintBottom_toBottomOf="#+id/seekbar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#+id/seekbar"
app:srcCompat="#drawable/ic_dim_max" />
</android.support.constraint.ConstraintLayout>
UPDATED: Adapter full code
class IndividualLightsAdapter(private val context: Context,
private val data: MutableList<Lamp>,
private val lightCallback: (Lamp, Boolean) -> Unit,
private val lightBrightnessCallback: (lamp: Lamp, brightness: Int) -> Unit)
: RecyclerView.Adapter<IndividualLightsAdapter.LightViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LightViewHolder {
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(R.layout.light_item_new, parent, false)
return LightViewHolder(view)
}
override fun getItemCount(): Int = data.size
override fun onBindViewHolder(holder: LightViewHolder, position: Int) {
holder.bind(position)
}
inner class LightViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(position: Int) {
val lamp = data[position]
itemView.light_icon_image_view.setImageResource(lamp.imageId)
itemView.light_name_text_view.text = lamp.customName
itemView.light_gradient_circle.visibility = if (lamp is SmartLamp) View.VISIBLE else View.INVISIBLE
itemView.light_switch.isChecked = lamp.isTurnedOn
itemView.light_switch.setOnCheckedChangeListener { _, isChecked ->
itemView.brightness.visibility = if (isChecked) View.VISIBLE else View.GONE
lightCallback(lamp, isChecked)
}
setSeekBar()
itemView.seekbar.progress = lamp.brightness
itemView.seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
lightBrightnessCallback(lamp, progress)
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
}
})
}
private fun setSeekBar() {
val gradient = GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT,
intArrayOf(ContextCompat.getColor(context, R.color.grad_start), (ContextCompat.getColor(context, R.color.grad_end))))
gradient.cornerRadius = context.resources.getDimension(R.dimen.corner_radius_outer)
val progressLayer = ClipDrawable(gradient, Gravity.START, ClipDrawable.HORIZONTAL)
val background = GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, intArrayOf(Color.BLACK, Color.BLACK))
background.cornerRadius = context.resources.getDimension(R.dimen.corner_radius_inner)
// TODO Calculate padding dynamically
val backgroundLayer = InsetDrawable(background,
context.resources.getDimension(R.dimen.padding_inset_left).toInt(),
context.resources.getDimension(R.dimen.padding_inset_top).toInt(),
context.resources.getDimension(R.dimen.padding_inset_right).toInt(),
context.resources.getDimension(R.dimen.padding_inset_bottom).toInt())
itemView.seekbar.thumb.setTint((ContextCompat.getColor(context, R.color.color_thumb)))
itemView.seekbar.progressDrawable = LayerDrawable(arrayOf<Drawable>(backgroundLayer, progressLayer))
}
}
}
You shouldn't hide the view that is an item of recyclerView.
It doesn't work properly because of its recycling mechanism.
You just need to remove/add the item to be able to do the same effect.
you should has the below methods on your RecyclerView adapter
private void deleteItem(int position) {
if (position != RecyclerView.NO_POSITION) {
myList.remove(position);
notifyItemRemoved(position);
}
}
private void addItem(int position, MyModel model) {
if (position != RecyclerView.NO_POSITION) {
myList.add(position, model);
notifyItemInserted(position);
}
}