Skip to content

Instantly share code, notes, and snippets.

@iamnaran
Created February 8, 2021 15:28
Show Gist options
  • Save iamnaran/51bf01d836241a75b1f2fb2a05d53004 to your computer and use it in GitHub Desktop.
Save iamnaran/51bf01d836241a75b1f2fb2a05d53004 to your computer and use it in GitHub Desktop.
<?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">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_to_refresh"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp">
<include
android:id="@+id/title_layout"
layout="@layout/item_title_profile"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<include
android:id="@+id/search_layout"
layout="@layout/item_search_notes"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title_layout" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingTop="10dp"
android:layoutAnimation="@anim/layout_animation"
android:paddingBottom="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/search_layout" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</layout>
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView 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:layout_margin="8dp"
app:cardBackgroundColor="@color/colorLightGrey"
app:cardCornerRadius="8dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView4"
android:layout_width="match_parent"
android:layout_height="180dp"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
<TextView
android:id="@+id/textView15"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:fontFamily="@font/poppins_regular"
android:includeFontPadding="false"
android:lineSpacingExtra="2dp"
android:lineSpacingMultiplier="1.2"
android:paddingStart="10dp"
android:paddingTop="4dp"
android:paddingEnd="10dp"
android:minLines="2"
android:paddingBottom="16dp"
android:text="@string/language_subtitle"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView16">
</TextView>
<TextView
android:id="@+id/textView16"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:fontFamily="@font/poppins_bold"
android:includeFontPadding="false"
android:lineSpacingExtra="2dp"
android:maxLines="1"
android:padding="5dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:text="DEC 20, 2015"
android:textSize="16sp"
android:textColor="@color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView4">
</TextView>
<ImageView
android:id="@+id/share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/background_notes_edit"
android:padding="10dp"
android:src="@drawable/ic_share_15dp"
android:layout_marginEnd="15dp"
app:layout_constraintBottom_toBottomOf="@+id/imageView4"
app:layout_constraintEnd_toStartOf="@+id/edit"
app:layout_constraintTop_toBottomOf="@+id/imageView4"
app:layout_constraintVertical_bias="0.485">
</ImageView>
<ImageView
android:id="@+id/edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:background="@drawable/background_notes_edit"
android:padding="10dp"
android:src="@drawable/ic_edit_pen"
app:layout_constraintBottom_toBottomOf="@+id/imageView4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView4">
</ImageView>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
@Entity
data class Note(
@PrimaryKey
val userNotesId: Int,
val pinLocation: String,
val pinNote: String? = null,
val user: Int? = null,
val base64Png: String? = null,
var lastRefreshed: Date? = null
)
open class NotesAdapter : RecyclerView.Adapter<NotesAdapter.DataViewHolder>(), Filterable {
var notesList: ArrayList<Note> = ArrayList()
var notesListFiltered: ArrayList<Note> = ArrayList()
var onItemClick: ((Note) -> Unit)? = null
inner class DataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
init {
itemView.setOnClickListener {
onItemClick?.invoke(notesListFiltered[adapterPosition])
}
}
fun bind(result: Note) {
itemView.textView15.text = result.pinLocation
// itemView.textView16.text = result.pinNote
//decode base64 string to image
val decodedString: ByteArray = Base64.decode(result.base64Png, Base64.DEFAULT)
val decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.size)
itemView.imageView4.setImageBitmap(decodedByte)
itemView.imageView4.scaleType = ImageView.ScaleType.CENTER_CROP
// Glide.with(itemView.imageView4.context).load(result.base64Png).into(itemView.imageView4)
Log.e("bind: ", result.pinLocation)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = DataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_row_notes, parent,
false
)
)
override fun onBindViewHolder(holder: DataViewHolder, position: Int) {
holder.bind(notesListFiltered[position])
}
override fun getItemCount(): Int = notesListFiltered.size
fun addData(list: List<Note>) {
notesList = list as ArrayList<Note>
notesListFiltered = notesList
notifyDataSetChanged()
}
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
val charString = constraint?.toString() ?: ""
if (charString.isEmpty()) notesListFiltered = notesList else {
val filteredList = ArrayList<Note>()
notesList
.filter { it.pinLocation.contains(constraint!!) }
.forEach { filteredList.add(it) }
notesListFiltered = filteredList
Log.e( "perform t1: ",filteredList.size.toString() )
// it.pinNote!!.toLowerCase(Locale.ROOT).contains(charString.toLowerCase(
// Locale.ROOT
// )
// ) or
}
return FilterResults().apply { values = notesListFiltered }
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
notesListFiltered = if(results?.values == null)
ArrayList<Note>()
else
results.values as ArrayList<Note>
notifyDataSetChanged()
Log.e( "performFiltering:1 ","called"+ notesListFiltered.size )
// notesListFiltered = results?.values as ArrayList<Note>
// notifyDataSetChanged()
}
}
}
@AndroidEntryPoint
class NotesFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener , SearchView.OnQueryTextListener {
companion object {
val TAG = NotesFragment::class.qualifiedName
}
private val notesViewModel: NotesViewModel by viewModels()
private var _binding: FragmentNotesBinding? = null
private val binding get() = _binding!!
private lateinit var notesAdapter: NotesAdapter
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = DataBindingUtil.inflate<ViewDataBinding>(
inflater, R.layout.fragment_notes, container, false
) as FragmentNotesBinding?
val view = binding.root
setUpViews()
doNotesObserveWork()
return view
}
private fun setUpViews() {
_binding!!.titleLayout.findViewById<TextView>(R.id.toolbar_title).text =
getString(R.string.notes)
_binding!!.recyclerView.layoutManager = LinearLayoutManager(
activity,
LinearLayoutManager.VERTICAL, false
)
notesAdapter = NotesAdapter()
_binding!!.recyclerView.adapter = notesAdapter
notesViewModel.getAllNotes(false)
_binding!!.swipeToRefresh.setOnRefreshListener(this)
_binding!!.searchLayout.findViewById<SearchView>(R.id.search_view).setOnQueryTextListener(this)
}
private fun doNotesObserveWork() {
notesViewModel.notes.observe(viewLifecycleOwner, {
when (it.status) {
Status.SUCCESS -> {
setRefreshStatus(false)
notesAdapter.addData(it.data!!)
_binding!!.recyclerView.scheduleLayoutAnimation()
}
Status.LOADING -> {
// binding.loginButton.isEnabled = false
// binding.progressBar.visibility = View.VISIBLE
}
Status.ERROR -> {
setRefreshStatus(false)
//Handle Error
// Toast.makeText(this, it.message, Toast.LENGTH_LONG).show()
// Log.d("error", it.toString())
// binding.loginButton.isEnabled = true
// binding.progressBar.visibility = View.INVISIBLE
}
}
})
}
override fun onRefresh() {
if (_binding!!.swipeToRefresh.isRefreshing) {
notesViewModel.getAllNotes(true)
}
}
private fun setRefreshStatus(status: Boolean) {
_binding!!.swipeToRefresh.isRefreshing = status
}
override fun onQueryTextSubmit(query: String?): Boolean {
notesAdapter.getFilter().filter(query)
return false
}
override fun onQueryTextChange(newText: String?): Boolean {
notesAdapter.getFilter().filter(newText)
return false;
}
}
class NotesViewModel @ViewModelInject constructor(
private val mainRepository: MainRepositoryImpl,
private val networkHelper: NetworkHelper,
private var preferencesHelper: PreferencesHelper
) : ViewModel() {
private val _notes = MediatorLiveData<Resource<List<Note>>>()
val notes: LiveData<Resource<List<Note>>>
get() = _notes
private var notesSource :LiveData<Resource<List<Note>>> = MutableLiveData()
fun getAllNotes(forceRefresh:Boolean){
viewModelScope.launch (Dispatchers.Main) {
_notes.removeSource(notesSource)
withContext(Dispatchers.IO){
notesSource = mainRepository.getNotedWithCache(forceRefresh)
}
_notes.addSource(notesSource){
Log.e( "doNotesObserveWork: ","cakked ")
_notes.value = it
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment