How to implement tabLayout floatingActionButton and toobar together in jetpack compose - android

I am trying to implement toobar, tabLayout and floatingActionButton in compose but not able to get all three of them simultaneously. I am getting either tabLayout or floatingActionButton. I think i am not able to change the position of floatingActionButton without Scaffold.
Main Activity:
`package com.example.tryingcompose
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.tryingcompose.ui.theme.TryingComposeTheme
import com.google.accompanist.pager.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
#OptIn(ExperimentalPagerApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
TryingComposeTheme {
Main()
}
}
}
}
#ExperimentalPagerApi
#Preview
#Composable
private fun Main() {
Column {
HandleToolBar()
val pagerState : PagerState = rememberPagerState(pageCount = 3)
HandleTabLayout(pagerState)
HandleFab()
}
}
#Preview
#Composable
private fun HandleToolBar() {
TopAppBar(
title = {
Text(
text = stringResource(id = R.string.app_name),
color = Color.White
)
},
actions = {
IconButton(onClick = { /*TODO*/ }) {
Icon(ImageVector.vectorResource(R.drawable.ic_outline_camera_alt_24), "CameraIcon", tint = Color.White)
}
IconButton(onClick = { /*TODO*/ }) {
Icon(Icons.Filled.Search, "SearchIcon", tint = Color.White)
}
IconButton(onClick = { /*TODO*/ }) {
Icon(Icons.Filled.MoreVert, "CameraIcon", tint = Color.White)
}
},
backgroundColor = Color(AppConstants.whatsappColor)
)
}
#ExperimentalPagerApi
#Composable
private fun HandleTabLayout(pagerState: PagerState) {
val list : List<String> = listOf(
stringResource(id = R.string.chats),
stringResource(id = R.string.status),
stringResource(id = R.string.calls)
)
val scope : CoroutineScope = rememberCoroutineScope()
TabRow(
selectedTabIndex = pagerState.currentPage,
backgroundColor = Color(AppConstants.whatsappColor),
contentColor = Color.White,
indicator = { tabPositions ->
TabRowDefaults.Indicator(
Modifier.pagerTabIndicatorOffset(pagerState, tabPositions),
height = 4.dp,
color = Color.White
)
}
) {
list.forEachIndexed { index, _ ->
Tab(
text = {
Text(
list[index],
color = if (pagerState.currentPage == index) Color.White else Color.LightGray
)
},
selected = pagerState.currentPage == index,
onClick = {
scope.launch {
pagerState.animateScrollToPage(index)
}
}
)
}
}
HorizontalPager(state = pagerState) { page ->
when(page) {
0 -> TabContentScreen(data = stringResource(id = R.string.chats))
1 -> TabContentScreen(data = stringResource(id = R.string.status))
2 -> TabContentScreen(data = stringResource(id = R.string.calls))
}
}
}
#Composable
private fun TabContentScreen(data : String) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = data,
style = MaterialTheme.typography.h5,
color = Color.Red,
fontWeight = FontWeight.Bold,
[![enter image description here](https://i.stack.imgur.com/JS7bP.png)](https://i.stack.imgur.com/JS7bP.png)
textAlign = TextAlign.Center
)
}
}
#Preview
#Composable
private fun HandleFab() {
FloatingActionButton(onClick = { /*TODO*/ }) {
Icon(
ImageVector.vectorResource(id = R.drawable.ic_baseline_contacts_24),
"Contacts"
)
}
}
AppConstants Class:
package com.example.tryingcompose
class AppConstants {
companion object {
val whatsappColor: Long = 0xFF338E3A
}
}
Also added these 3 dependencies:
implementation "com.google.accompanist:accompanist-systemuicontroller:0.27.0"
implementation "com.google.accompanist:accompanist-pager:0.13.0"
implementation "com.google.accompanist:accompanist-pager-indicators:0.13.0"`
`
I tried using Scaffold and tried to put toobar and tabLayout in different Column then floatingActionButton Appears but then i am not able to place my tabLayout
#ExperimentalPagerApi
#Preview
#Composable
private fun Main() {
val pagerState : PagerState = rememberPagerState(pageCount = 3)
Column {[![enter image description here](https://i.stack.imgur.com/WjZff.png)](https://i.stack.imgur.com/WjZff.png)
Scaffold(
topBar = {
TopAppBar(
title = {
Text(
text = stringResource(id = R.string.app_name),
color = Color.White
)
},
actions = {
IconButton(onClick = { /*TODO*/ }) {
Icon(ImageVector.vectorResource(R.drawable.ic_outline_camera_alt_24), "CameraIcon", tint = Color.White)
}
IconButton(onClick = { /*TODO*/ }) {
Icon(Icons.Filled.Search, "SearchIcon", tint = Color.White)
}
IconButton(onClick = { /*TODO*/ }) {
Icon(Icons.Filled.MoreVert, "CameraIcon", tint = Color.White)
}
},
backgroundColor = Color(AppConstants.whatsappColor)
)
},
floatingActionButton = {
FloatingActionButton(onClick = { /*TODO*/ }) {
Icon(
ImageVector.vectorResource(id = R.drawable.ic_baseline_contacts_24),
"Contacts"
)
}
}
) {
}
HandleTabLayout(pagerState)
}
}

Related

Questions are not getting fetched when using floating action button

I am making a quiz app. My main activity has blocks. Each block has a date written over it. the date act as title while fetching information from firebase. These blocks are working perfectly fine, (fetching questions).I also have a floating action button, on clicking displays a calender and we can select date from there and access quiz for that particular day, but it is not working .
Home screen : home screen
Interface while accessing question from block : image
Interface while accessing through floating action bar :image
Main Activity:
package com.example.quiz.activities
import android.annotation.SuppressLint
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.MenuItem
import android.widget.Toast
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.recyclerview.widget.GridLayoutManager
import com.example.quiz.R
import com.example.quiz.adapters.QuizAdapter
import com.example.quiz.databinding.ActivityMainBinding
import com.example.quiz.models.Quiz
import com.google.android.material.datepicker.MaterialDatePicker
import com.google.firebase.firestore.DocumentSnapshot
import com.google.firebase.firestore.FirebaseFirestore
import java.text.SimpleDateFormat
import java.util.*
class MainActivity() : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
lateinit var adapter: QuizAdapter
private var quizList = mutableListOf<Quiz>()
lateinit var firestore : FirebaseFirestore
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setUpViews()
}
fun setUpViews(){
setUpFirestore()
setUpDrawerLayout()
setUpRecyclerView()
setUpDatePicker()
}
#SuppressLint("SimpleDateFormat")
private fun setUpDatePicker() {
// val btnDatePicker = binding.btnDatePicker
binding.btnDatePicker.setOnClickListener{
val datePicker = MaterialDatePicker.Builder.datePicker().build()
datePicker.show(supportFragmentManager,"DatePicker")
datePicker.addOnPositiveButtonClickListener {
Log.d("DATEPICKER",datePicker.headerText)
val dateFormatter = SimpleDateFormat("dd-mm-yyyy")
val date = dateFormatter.format(Date(it))
val intent = Intent(this,QuestionActivity::class.java)
intent.putExtra("DATE",date)
startActivity(intent)
}
datePicker.addOnNegativeButtonClickListener {
Log.d("DATEPICKER",datePicker.headerText)
}
datePicker.addOnCancelListener {
Log.d("DATEPICKER","Date Picker was cancelled")
}
}
}
private fun setUpFirestore() {
firestore = FirebaseFirestore.getInstance()
val collectionReference = firestore.collection("quizzes")
collectionReference.addSnapshotListener{ value, error ->
if(value == null || error != null){
Toast.makeText(this,"Error fetching data",Toast.LENGTH_SHORT).show()
return#addSnapshotListener
}
Log.d("DATA", value.toObjects(Quiz::class.java).toString())
quizList.clear()
quizList.addAll(value.toObjects(Quiz::class.java))
adapter.notifyDataSetChanged()
}
}
private fun setUpRecyclerView(){
val quizRecyclerView = binding.quizRecyclerView
adapter = QuizAdapter(this,quizList)
quizRecyclerView.layoutManager = GridLayoutManager(this,2)
quizRecyclerView.adapter = adapter
}
private fun setUpDrawerLayout(){
val appBar = binding.appBar
val mainDrawer = binding.mainDrawer
val navigationView = binding.navigationView
setSupportActionBar(appBar)
actionBarDrawerToggle = ActionBarDrawerToggle(this,mainDrawer,
R.string.app_name,
R.string.app_name
)
actionBarDrawerToggle.syncState()
navigationView.setNavigationItemSelectedListener {
val intent = Intent(this,ProfileActivity::class.java)
startActivity(intent)
mainDrawer.closeDrawers()
true
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (actionBarDrawerToggle.onOptionsItemSelected(item)){
return true
}
return super.onOptionsItemSelected(item)
}
}
Quiz adapter
package com.example.quiz.adapters
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.cardview.widget.CardView
import androidx.recyclerview.widget.RecyclerView
import com.example.quiz.R
import com.example.quiz.activities.QuestionActivity
import com.example.quiz.models.Quiz
import com.example.quiz.utils.ColorPicker
import com.example.quiz.utils.IconPicker
class QuizAdapter(val context: Context, val quizzes: List<Quiz>) :
RecyclerView.Adapter<QuizAdapter.QuizViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuizViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.quiz_item,parent,false)
return QuizViewHolder(view)
}
override fun onBindViewHolder(holder: QuizViewHolder, position: Int) {
holder.textViewTitle.text = quizzes[position].title
holder.cardContainer.setCardBackgroundColor(Color.parseColor(ColorPicker.getColor()))
holder.iconView.setImageResource(IconPicker.getIcon())
holder.itemView.setOnClickListener{
Toast.makeText(context,quizzes[position].title,Toast.LENGTH_SHORT).show()
val intent = Intent(context , QuestionActivity::class.java)
intent.putExtra("DATE",quizzes[position].title)
context.startActivity(intent)
}
}
override fun getItemCount(): Int {
return quizzes.size
}
inner class QuizViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var textViewTitle: TextView = itemView.findViewById(R.id.quizTitle)
var iconView: ImageView = itemView.findViewById(R.id.quizIcon)
var cardContainer: CardView = itemView.findViewById(R.id.cardContainer)
}
}
Question Activity
package com.example.quiz.activities
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.Toast
import androidx.core.view.allViews
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.quiz.R
import com.example.quiz.adapters.OptionAdapter
import com.example.quiz.databinding.ActivityQuestionBinding
import com.example.quiz.models.Question
import com.google.firebase.firestore.FirebaseFirestore
import com.example.quiz.models.Quiz
import com.google.gson.Gson
class QuestionActivity : AppCompatActivity() {
var quizzes : MutableList<Quiz>? = null
var questions : MutableMap<String,Question>? = null
var index = 1
lateinit var firestore : FirebaseFirestore
private lateinit var binding: ActivityQuestionBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityQuestionBinding.inflate(layoutInflater)
setContentView(binding.root)
setUpFireStore()
setUpEventListener()
}
private fun setUpEventListener() {
val btnPrevious = binding.btnPrevious
val btnSubmit = binding.btnSubmit
val btnNext = binding.btnNext
btnPrevious.setOnClickListener{
index--
bindViews()
}
btnNext.setOnClickListener{
index++
bindViews()
}
btnSubmit.setOnClickListener{
Log.d("FINAL QUIZ",questions.toString())
val intent = Intent(this,ResultActivity::class.java)
val json = Gson().toJson(quizzes!![0])
intent.putExtra("QUIZ",json)
startActivity(intent)
}
}
private fun setUpFireStore() {
val firestore = FirebaseFirestore.getInstance()
var date = intent.getStringExtra("DATE")
if (date!= null){
firestore.collection("quizzes").whereEqualTo("title",date)
.get()
.addOnSuccessListener {
if (it != null && !it.isEmpty){
Log.d("DATA",it.toObjects(Quiz::class.java).toString())
quizzes = it.toObjects(Quiz::class.java)
questions = quizzes!![0].questions
bindViews()
}
else{
Toast.makeText(this,"Error Fetching data",Toast.LENGTH_SHORT).show()
}
}
}
}
private fun bindViews() {
val btnPrevious = binding.btnPrevious
val btnSubmit = binding.btnSubmit
val btnNext = binding.btnNext
val description = binding.description
val optionList = binding.optionList
btnPrevious.visibility = View.GONE
btnSubmit.visibility = View.GONE
btnNext.visibility = View.GONE
if (index == 1) {
btnNext.visibility = View.VISIBLE
}
else if(index == questions!!.size){
btnSubmit.visibility = View.VISIBLE
btnPrevious.visibility = View.VISIBLE
}
else{
btnNext.visibility = View.VISIBLE
btnPrevious.visibility = View.VISIBLE
}
val question = questions!!["question$index"]
question?.let {
description.text = it.description
val optionAdapter = OptionAdapter(this,it)
optionList.layoutManager = LinearLayoutManager(this)
optionList.adapter = optionAdapter
optionList.setHasFixedSize(true)
}
}
}
No logcat error is shown but this error is shown in run section : E/RecyclerView: No adapter attached; skipping layout

Why does my app activity keep pausing, whenever it is called from within a recylerView?

I am trying to build an app that uses the youtube API. I need to call the search API, whenever the user searches for something and then display the results in a new activity(SearchResultsActivity). However the scenario I get is that my app, rather than opening the SearchResultsActivity gets redirected to the MainActivity.
The scenario is recorded, and can be better understood through this https://drive.google.com/file/d/1WESzXbRbjhmKCY1gfUq1d2gllIEsILCf/view?usp=sharing.
I want to know what is causing the SearchResultsActivity to be paused by itself and MainActivity being restarted instead. I tried logging the lifecycles to know what was happening and I found this:
Also Search box activity here means the SearchActivity:
package com.example.mytube.UI
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.view.View
import android.widget.EditText
import android.widget.ImageView
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.mytube.R
import com.example.mytube.adapters.SearchedHistoryAdapter
import com.example.mytube.db.SearchDatabase
import com.example.mytube.repository.VideosRepository
class SearchActivity : AppCompatActivity() {
lateinit var searchAdapter: SearchedHistoryAdapter
lateinit var viewModel: VideosViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_search)
val repository = VideosRepository(SearchDatabase.getSearchDatabase(this))
val viewModelFactory = VideosViewModelProviderFactory(repository)
viewModel = ViewModelProvider(this,viewModelFactory).get(VideosViewModel::class.java)
val recyclerView = findViewById<RecyclerView>(R.id.searched_terms)
searchAdapter = SearchedHistoryAdapter()
recyclerView.apply {
adapter = searchAdapter
layoutManager = LinearLayoutManager(this#SearchActivity)
}
val backButton = findViewById<ImageView>(R.id.ivGoback)
backButton.apply {
setOnClickListener {
finish()
}
}
val searchBar = findViewById<EditText>(R.id.search_box)
val searchBtn = findViewById<ImageView>(R.id.ivSearch)
searchBtn.setOnClickListener {
if (searchBar.text.toString().isNotEmpty()) {
viewModel.insertSearchItem(searchBar.text.toString())
val intent = Intent(applicationContext, SearchResultsActivity::class.java)
intent.putExtra("searchQuery", searchBar.text)
startActivity(intent)
}
}
searchBar.setOnKeyListener(View.OnKeyListener{v, keyCode, event ->
if (event.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER) {
if (searchBar.text.toString().isNotEmpty()) {
viewModel.insertSearchItem(searchBar.text.toString())
}
return#OnKeyListener true
}
return#OnKeyListener false
})
viewModel.getSearchHistory().observe(this, Observer { searchItems ->
searchAdapter.differ.submitList(searchItems)
})
}
override fun onPause() {
super.onPause()
Log.d("searched", "Search box activity paused")
}
override fun onStop() {
super.onStop()
Log.d("searched", "Search box activity stopped")
}
override fun onDestroy() {
super.onDestroy()
Log.d("searched", "Search box activity destroyed")
}
}
The SearchResultsActivity:
package com.example.mytube.UI
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.AbsListView
import android.widget.ProgressBar
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.mytube.R
import com.example.mytube.adapters.VideosAdapter
import com.example.mytube.db.SearchDatabase
import com.example.mytube.repository.VideosRepository
import com.example.mytube.util.Resource
class SearchResultsActivity : AppCompatActivity() {
lateinit var viewModel: VideosViewModel
lateinit var videosAdapter: VideosAdapter
var searchQuery = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_search_results)
searchQuery = intent.getStringExtra("searchQuery").toString()
val repository = VideosRepository(SearchDatabase.getSearchDatabase(this))
val viewModelFactory = VideosViewModelProviderFactory(repository)
viewModel = ViewModelProvider(this,viewModelFactory).get(VideosViewModel::class.java)
videosAdapter = VideosAdapter(viewModel)
val recyclerView = findViewById<RecyclerView>(R.id.videos)
recyclerView.apply {
layoutManager = LinearLayoutManager(this#SearchResultsActivity)
adapter = videosAdapter
addOnScrollListener(this#SearchResultsActivity.scrollListener)
}
val progressBar = findViewById<ProgressBar>(R.id.paginationProgressBar)
viewModel.getSearchResults(searchQuery)
viewModel.searchResults.observe(this, Observer { resource ->
when(resource) {
is Resource.Success -> {
hideProgressBar(progressBar)
resource.data?.let { videoResponse ->
if (viewModel.nextSearchPageId != videoResponse.nextPageToken) {
viewModel.nextSearchPageId = videoResponse.nextPageToken
viewModel.searchedVideos.addAll(videoResponse.items)
// videoResponse.items.forEach { viewModel.getChannel(it.snippet.channelId) }
Log.d("Channels", viewModel.channels.toString())
videosAdapter.differ.submitList(viewModel.searchedVideos.toList())
}
else {
Log.d("Videos", "next token dekh ${viewModel.nextPageId}")
videosAdapter.differ.submitList(viewModel.searchedVideos.toList())
}
}
}
is Resource.Error -> {
hideProgressBar(progressBar)
Log.e("Videos", resource.message.toString())
}
is Resource.Loading -> {
showProgressBar(progressBar)
}
}
})
viewModel.channelResponse.observe(this, Observer { resource ->
when (resource) {
is Resource.Success -> {
resource.data?.let { channels ->
viewModel.channels.set(channels.items[0].id, channels.items[0])
// videosAdapter.differ.submitList(viewModel.videos.toList())
}
}
is Resource.Error -> {
Log.e("Channels", resource.message.toString())
}
is Resource.Loading -> {
Log.d("Channels", "Waiting")
}
}
})
}
private fun hideProgressBar(bar: ProgressBar) {
bar.visibility = View.INVISIBLE
isLoading = false
}
private fun showProgressBar(bar: ProgressBar){
bar.visibility = View.VISIBLE
isLoading = true
}
var isScrolling = false
var isLoading = false
val scrollListener = object: RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
isScrolling = true
}
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val manager = recyclerView.layoutManager as LinearLayoutManager
val currentItems = manager.childCount
val totaltItems = manager.itemCount
val scrolledItems = manager.findFirstVisibleItemPosition()
if (isScrolling && totaltItems == currentItems + scrolledItems && !isLoading && viewModel.searchedVideos.size <= 1_000_000) {
viewModel.getNextSearchResults(searchQuery)
isScrolling = false
} else {
videosAdapter.differ.submitList(viewModel.searchedVideos.toList())
recyclerView.setPadding(0, 0, 0, 0)
Log.d("Videos", viewModel.searchedVideos.size.toString())
}
}
}
override fun onPause() {
super.onPause()
Log.d("searched", "Search Results Activity paused")
}
override fun onStop() {
super.onStop()
Log.d("searched", "Search Results Activity stopped")
}
override fun onDestroy() {
super.onDestroy()
Log.d("searched", "Search Results Activity destroyed")
}
}
The logcat shows the following error:
2021-09-28 12:51:06.200 1207-2988/? W/ActivityTaskManager: Force finishing activity com.example.mytube/.UI.SearchResultsActivity
For recreating the error, here is the gitHub repo to the app: https://github.com/AkhilrajNambiar/MyTube-1
Thanks in advance!

How to define Imageview in getter setter method

Hello guy i am new to Kotlin android and working on a demo in this demo i am trying to get an image from the gallery and set it in my recyclerview but i am getting the solution requesting you to please find me a solution Thanks in Advance!!
This is my CustomAdapter.kt:-
package com.example.itemgetset
import android.app.Activity
import android.app.AlertDialog
import android.content.ContentValues.TAG
import android.content.Intent
import android.os.Build
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.PopupMenu
import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.snackbar.Snackbar
#Suppress("UNREACHABLE_CODE")
class CustomAdapter(
private var activity: Activity,
private val userList: ArrayList<ProductInfoGetSet>,
private var isforlist: Boolean,
) :
RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val itemview=
LayoutInflater.from(parent.context).inflate(R.layout.list_layout, parent, false)
return ViewHolder(itemview)
}
#RequiresApi(Build.VERSION_CODES.N)
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val productInfoGetSet: ProductInfoGetSet = userList[position]
holder.image = productInfoGetSet.image
holder.txtId.text = productInfoGetSet.id
holder.txtName.text = productInfoGetSet.name
holder.txtQuantity.text = productInfoGetSet.quantity
holder.txtPrice.text = productInfoGetSet.price
val id = userList[position].id
Log.e(TAG, "List item ID: $id")
holder.buttonViewOption.setOnClickListener {
val popup = PopupMenu(activity, holder.buttonViewOption)
popup.inflate(R.menu.pop_menu)
popup.setOnMenuItemClickListener { item ->
when (item.itemId) {
R.id.edit -> {
val intent = Intent(activity, AddDetails::class.java)
intent.putExtra("isFor", "Update")
intent.putExtra("id", productInfoGetSet.id)
intent.putExtra("image",productInfoGetSet.image)
intent.putExtra("name", productInfoGetSet.name)
intent.putExtra("quantity", productInfoGetSet.quantity)
intent.putExtra("price", productInfoGetSet.price)
activity.startActivity(intent)
}
R.id.delete -> {
val builder = AlertDialog.Builder(activity)
builder.setTitle("Delete")
builder.setMessage("Do you want to delete the item?")
builder.setPositiveButton("Yes") { _, _ ->
userList.removeAt(position)
notifyItemRemoved(position)
val snack = Snackbar
.make(
holder.linearly,
"Item was removed from the list.",
Snackbar.LENGTH_SHORT
)
snack.show()
}
builder.setNegativeButton("No") { _, _ ->
}
val dialog: AlertDialog = builder.create()
dialog.show()
}
}
false
}
popup.show()
}
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getItemCount(): Int {
return userList.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val txtName = itemView.findViewById(R.id.txt_name) as TextView
val txtId = itemView.findViewById(R.id.txt_id) as TextView
var image = itemView.findViewById(R.id.imageView2) as ImageView
val txtQuantity = itemView.findViewById(R.id.txt_quantity) as TextView
val txtPrice = itemView.findViewById(R.id.txt_price) as TextView
val linearly: LinearLayout = itemView.findViewById(R.id.linearlayout)
val buttonViewOption = itemView.findViewById<View>(R.id.txt_Options) as TextView
}
}
in this adapter i gent and error on holder.image = productInfoGetSet.image this line and not get solved.
This is my AddDeatils.kt:-
package com.example.itemgetset
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.os.Message
import android.provider.MediaStore
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.ImageView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import kotlinx.android.synthetic.main.add_item.*
import kotlinx.android.synthetic.main.list_layout.*
class AddDetails : AppCompatActivity() {
private lateinit var btnSubmit: Button
private lateinit var edtName: EditText
private lateinit var edtQuantity: EditText
private lateinit var edtPrice: EditText
private lateinit var imageview: ImageView
companion object {
private const val IMAGE_PICK_CODE = 1000
private const val PERMISSION_CODE = 1001
}
#SuppressLint("SetTextI18n", "ResourceType")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.add_item)
supportActionBar?.hide()
findViewById()
onclick()
if (intent.getStringExtra("isFor").equals("Update")) {
intent.getStringExtra("image")?.toInt()?.let { imageview.setImageResource(it) }
edtName.setText(intent.getStringExtra("name"))
edtQuantity.setText(intent.getStringExtra("quantity"))
edtPrice.setText(intent.getStringExtra("price"))
}
}
private fun findViewById() {
btnSubmit = findViewById(R.id.btn_submit)
edtName = findViewById(R.id.edt_name)
edtQuantity = findViewById(R.id.edt_quantity)
edtPrice = findViewById(R.id.edt_price)
imageview = findViewById(R.id.image_view)
}
#SuppressLint("ResourceType")
private fun onclick() {
btnSubmit.setOnClickListener {
when {
edtName.text.trim().isEmpty() -> {
edtName.error = "Please Enter Product Name"
Toast.makeText(
applicationContext,
"Please Enter Product Name",
Toast.LENGTH_SHORT
)
.show()
}
edtQuantity.text.trim().isEmpty() -> {
edtQuantity.error = "Please Enter Product Quantity"
Toast.makeText(
applicationContext,
"Please Enter Product Quantity",
Toast.LENGTH_SHORT
).show()
}
edtPrice.text.trim().isEmpty() -> {
edtPrice.error = "Please Enter Product Price"
Toast.makeText(
applicationContext,
"Please Enter Product Price",
Toast.LENGTH_SHORT
)
.show()
}
else -> {
Toast.makeText(
applicationContext,
"Product Added Successfully ",
Toast.LENGTH_SHORT
).show()
val temp = Temp()
temp.image = imageview.toString()
temp.name = edtName.text.toString()
temp.quantity = edtQuantity.text.toString()
temp.price = edtPrice.text.toString()
if (intent.getStringExtra("isFor").equals("Update")) {
temp.id = intent.getStringExtra("id").toString()
}
val message: Message = Message.obtain()
message.what = 111
message.obj = temp
MainActivity.handler.sendMessage(message)
finish()
}
}
}
imageview.setOnClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) ==
PackageManager.PERMISSION_DENIED
) {
val permissions = arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE)
requestPermissions(permissions, PERMISSION_CODE)
} else {
pickImageFromGallery()
}
} else {
pickImageFromGallery()
}
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
when (requestCode) {
PERMISSION_CODE -> {
if (grantResults.isNotEmpty() && grantResults[0] ==
PackageManager.PERMISSION_GRANTED
) {
pickImageFromGallery()
} else {
Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show()
}
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
private fun pickImageFromGallery() {
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
startActivityForResult(intent, IMAGE_PICK_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK && requestCode == IMAGE_PICK_CODE) {
imageview.setImageURI(data?.data)
super.onActivityResult(requestCode, resultCode, data)
}
}
}
And this is my MainActivity.kt:-
package com.example.itemgetset
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Button
import android.widget.GridView
import android.widget.LinearLayout
import android.widget.ListView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
#Suppress("DEPRECATION")
class MainActivity : AppCompatActivity() {
lateinit var activity: Activity
val userList = ArrayList<ProductInfoGetSet>()
private lateinit var btnProductAdd: Button
lateinit var llEmptyView: LinearLayout
lateinit var llMain: LinearLayout
private var listView: ListView? = null
private var gridView: GridView? = null
lateinit var recyclerView: RecyclerView
private lateinit var llFab: LinearLayout
private lateinit var linearLayoutManager: LinearLayoutManager
private lateinit var gridLayoutManager: GridLayoutManager
private lateinit var adapter: CustomAdapter
private var isforlist = true
companion object {
var handler: Handler = Handler()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
activity = this
initView()
onClicks()
setUpData()
handler = #SuppressLint("HandlerLeak")
object : Handler() {
override fun handleMessage(msg: Message) {
if (msg.what == 111) {
val temp: Temp = msg.obj as Temp
if (temp.id == "") {
userList.add(
ProductInfoGetSet(
(userList.size + 1).toString(),
temp.image,
temp.name,
temp.quantity,
temp.price,
)
)
adapter = CustomAdapter(activity, userList, isforlist)
recyclerView.adapter = adapter
} else {
for (i in userList.indices) {
if (userList[i].id == temp.id) {
userList[i].id = temp.id
userList[i].image = temp.image
userList[i].name = temp.name
userList[i].quantity = temp.quantity
userList[i].price = temp.price
}
}
adapter.notifyDataSetChanged()
}
}
if (userList.size > 0) {
llEmptyView.visibility = View.GONE
llMain.visibility = View.VISIBLE
} else {
llEmptyView.visibility = View.VISIBLE
llMain.visibility = View.GONE
}
}
}
}
private fun changeLayoutManager() {
if (recyclerView.layoutManager == linearLayoutManager) {
recyclerView.layoutManager = gridLayoutManager
} else {
recyclerView.layoutManager = linearLayoutManager
}
}
private fun initView() {
btnProductAdd = findViewById(R.id.btn_product_add)
llFab = findViewById(R.id.ll_fab)
llEmptyView = findViewById(R.id.llEmptyView)
listView = findViewById(R.id.list_product)
gridView = findViewById(R.id.list_productGV)
llMain = findViewById(R.id.llMain)
recyclerView = findViewById(R.id.recycler_view)
recyclerView.layoutManager = LinearLayoutManager(this)
linearLayoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
gridLayoutManager = GridLayoutManager(this, 2)
}
private fun onClicks() {
btnProductAdd.setOnClickListener {
val intent = Intent(this#MainActivity, AddDetails::class.java)
intent.putExtra("isFor", "Add")
startActivity(intent)
}
llFab.setOnClickListener {
val intent = Intent(this#MainActivity, AddDetails::class.java)
intent.putExtra("isFor", "Add")
startActivity(intent)
}
}
private fun setUpData() {
if (userList.size > 0) {
llEmptyView.visibility = View.GONE
llMain.visibility = View.VISIBLE
} else {
llEmptyView.visibility = View.VISIBLE
llMain.visibility = View.GONE
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.menu_view) {
if (userList.size > 0) {
changeLayoutManager()
}
return true
}
return super.onOptionsItemSelected(item)
}
}
My ProductInfoGetSet.kt:-
package com.example.itemgetset
import android.widget.ImageView
class ProductInfoGetSet(
var id: String,
var image: ImageView,
var name: String,
var quantity: String,
var price: String
)
Temp.kt:-
package com.example.itemgetset
import android.widget.ImageView
class Temp {
var id: String = ""
var image: ImageView =
var name: String = ""
var quantity: String = ""
var price: String = ""
}
Thanks in advance!!
I understand you are new to Android. I will list down points below for you to understand clearly.
As a standard practice you must not use ImageView in any model as Model can only hold data.
Use databinding for views.
As suggested by Rupam Saini, you can use Glide or Picasso for image loading.
You can't pass imageView in bundle as it will create different object when you read it again. There is a chance of leaking context also.
Regarding your question
in this adapter i gent and error on holder.image = productInfoGetSet.image this line and not get solved.
You are trying to set an ImageView to another ImageView which is not correct. Temp file is incorrect, there is no value after = . So Temp file must also have error.
It'll be better if you show your ProductInfoGetSet class and the error logs.
You should not set the image directly
holder.image = productInfoGetSet.image
Instead you can get the image's URI and then set it like this
holder.image.setImageUri(imageUri)
If you are still getting issues then you can use the Glide library

Android Paging library, Recyclerview, Retrofit, MVVM

I'm trying to build an app with Android Architecture Components. I'm using TMDB API in my app. In my app, a user searches for a movie or series and gets the result. I've achieved this but I want to get all the pages from API with Paging library. (Endless Recyclerview) I've looked at several tutorials but I didn't get what I wanted. Please help me, I'm new with this Android Architecture Components. Thank you in advance.
The API result:
RecyclerViewMovieAdapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.martiandeveloper.muuvi.R
import com.martiandeveloper.muuvi.model.Movie
import kotlinx.android.synthetic.main.recyclerview_movie_item.view.*
class RecyclerViewMovieAdapter(private val movieList: ArrayList<Movie>) :
RecyclerView.Adapter<RecyclerViewMovieAdapter.RecyclerViewMovieViewHolder>() {
lateinit var context: Context
class RecyclerViewMovieViewHolder(var view: View) : RecyclerView.ViewHolder(view)
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): RecyclerViewMovieViewHolder {
context = parent.context
val view = LayoutInflater.from(context)
.inflate(R.layout.recyclerview_movie_item, parent, false)
return RecyclerViewMovieViewHolder(view)
}
override fun getItemCount(): Int {
return movieList.size
}
override fun onBindViewHolder(holder: RecyclerViewMovieViewHolder, position: Int) {
if (movieList[position].mediaType != "person") {
if (movieList[position].mediaType == "tv") {
val title =
movieList[position].originalName + " (" + movieList[position].firstAirDate?.split(
"-"
)?.get(0) + ")"
holder.view.recyclerview_movie_item_titleMTV.text = title
} else {
val title =
movieList[position].title + " (" + movieList[position].releaseDate?.split("-")
?.get(0) + ")"
holder.view.recyclerview_movie_item_titleMTV.text = title
}
holder.view.recyclerview_movie_item_voteAverageMTV.text =
movieList[position].voteAverage.toString()
Glide.with(context)
.load("https://image.tmdb.org/t/p/w300${movieList[position].posterPath}")
.placeholder(R.drawable.logo1)
.centerCrop()
.into(holder.view.recyclerview_movie_item_posterIV)
}
}
fun updateMovieList(newMovieList: List<Movie>) {
movieList.clear()
movieList.addAll(newMovieList)
notifyDataSetChanged()
}
}
Movie.kt
import com.google.gson.annotations.SerializedName
data class Movie(
#SerializedName("original_name")
val originalName: String?,
#SerializedName("genre_ids")
val genreIds: List<Int>?,
#SerializedName("media_type")
val mediaType: String?,
#SerializedName("name")
val name: String?,
#SerializedName("origin_country")
val originCountry: List<String>?,
#SerializedName("first_air_date")
val firstAirDate: String?,
#SerializedName("original_language")
val originalLanguage: String?,
#SerializedName("id")
val id: Int?,
#SerializedName("vote_average")
val voteAverage: Float?,
#SerializedName("overview")
val overview: String?,
#SerializedName("poster_path")
val posterPath: String?,
#SerializedName("title")
val title: String?,
#SerializedName("release_date")
val releaseDate: String?,
#SerializedName("original_title")
val originalTitle: String?)
MovieResult.kt
import com.google.gson.annotations.SerializedName
data class MovieResult(
#SerializedName("page")
val page: Int?,
#SerializedName("total_results")
val totalResults: Int?,
#SerializedName("total_pages")
val totalPages: Int?,
#SerializedName("results")
val results: ArrayList<Movie>?
)
MovieApi.kt
import com.martiandeveloper.muuvi.model.MovieResult
import io.reactivex.Single
import retrofit2.http.GET
import retrofit2.http.Query
interface MovieApi {
#GET("search/multi")
fun getMovie(
#Query("api_key") apiKey: String,
#Query("query") movie: String,
#Query("page") page: Int
): Single<MovieResult>
}
MovieService.kt
import com.martiandeveloper.muuvi.model.MovieResult
import io.reactivex.Single
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
const val API_KEY = "fb640042b4bc08f6f7f65fbd8573f2a9"
const val BASE_URL = "https://api.themoviedb.org/3/"
// https://api.themoviedb.org/3/search/multi?api_key=my_api_key&query=break&page=1
// https://image.tmdb.org/t/p/w342/or06FN3Dka5tukK1e9sl16pB3iy.jpg
class MovieService {
private val api =
Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build()
.create(MovieApi::class.java)
fun getData(movie: String, page: Int): Single<MovieResult> {
return api.getMovie(API_KEY, movie, page)
}
}
AddFragment.kt
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import com.martiandeveloper.muuvi.R
import com.martiandeveloper.muuvi.adapter.RecyclerViewMovieAdapter
import com.martiandeveloper.muuvi.databinding.FragmentAddBinding
import com.martiandeveloper.muuvi.viewmodel.AddViewModel
import kotlinx.android.synthetic.main.fragment_add.*
class AddFragment : Fragment(), View.OnClickListener {
private lateinit var vm: AddViewModel
private val adapter = RecyclerViewMovieAdapter(arrayListOf())
private lateinit var binding: FragmentAddBinding
private lateinit var layoutManager: LinearLayoutManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
vm = activity?.run {
ViewModelProviders.of(this)[AddViewModel::class.java]
} ?: throw Exception("Invalid activity")
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding =
DataBindingUtil.inflate(inflater, R.layout.fragment_add, container, false)
binding.addViewModel = vm
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initUI()
}
private fun initUI() {
setRecyclerView()
observe()
setProgress(isRecyclerViewGone = false, isProgressLLViewGone = true)
binding.isClearIVGone = true
setListeners()
fragment_add_movieSeriesET.requestFocus()
val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(fragment_add_movieSeriesET, InputMethodManager.SHOW_IMPLICIT)
}
private fun setRecyclerView() {
layoutManager = LinearLayoutManager(context)
fragment_add_mainRV.layoutManager = layoutManager
fragment_add_mainRV.adapter = adapter
}
private fun observe() {
vm.movieList.observe(viewLifecycleOwner, Observer { movieList ->
movieList?.let {
adapter.updateMovieList(it)
}
})
vm.isError.observe(viewLifecycleOwner, Observer { isError ->
isError?.let {
setProgress(isRecyclerViewGone = false, isProgressLLViewGone = true)
if (it) {
setToast(resources.getString(R.string.something_went_wrong_please_try_again_later))
}
}
})
vm.isLoading.observe(viewLifecycleOwner, Observer { isLoading ->
isLoading?.let {
if (it) {
setProgress(isRecyclerViewGone = true, isProgressLLViewGone = false)
} else {
setProgress(isRecyclerViewGone = false, isProgressLLViewGone = true)
}
}
})
vm.movieSeriesETContent.observe(viewLifecycleOwner, Observer {
if (it.isNotEmpty()) {
vm.refreshData(it, 1)
binding.isClearIVGone = false
} else {
adapter.updateMovieList(arrayListOf())
binding.isClearIVGone = true
}
})
}
private fun setProgress(isRecyclerViewGone: Boolean, isProgressLLViewGone: Boolean) {
if (vm.movieSeriesETContent.value != null) {
val text =
"${resources.getString(R.string.searching_for)} \"${vm.movieSeriesETContent.value}\"..."
binding.searchingFor = text
}
binding.isMainRVGone = isRecyclerViewGone
binding.isProgressLLGone = isProgressLLViewGone
}
private fun setToast(text: String) {
Toast.makeText(context, text, Toast.LENGTH_SHORT).show()
}
private fun setListeners() {
fragment_add_clearIV.setOnClickListener(this)
}
override fun onClick(v: View?) {
if (v != null) {
when (v.id) {
R.id.fragment_add_clearIV -> fragment_add_movieSeriesET.text.clear()
}
}
}
}
AddViewModel.kt
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.martiandeveloper.muuvi.model.MovieResult
import com.martiandeveloper.muuvi.model.Movie
import com.martiandeveloper.muuvi.service.MovieService
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.observers.DisposableSingleObserver
import io.reactivex.schedulers.Schedulers
class AddViewModel : ViewModel() {
private val movieService = MovieService()
private val disposable = CompositeDisposable()
val movieList = MutableLiveData<ArrayList<Movie>>()
val isError = MutableLiveData<Boolean>()
val isLoading = MutableLiveData<Boolean>()
val movieSeriesETContent = MutableLiveData<String>()
fun refreshData(movie: String, page: Int) {
isLoading.value = true
disposable.add(
movieService.getData(movie, page).subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object : DisposableSingleObserver<MovieResult>() {
override fun onSuccess(t: MovieResult) {
movieList.value = t.results
isError.value = false
isLoading.value = false
}
override fun onError(e: Throwable) {
isError.value = true
isLoading.value = false
}
})
)
}
}

MultiThreading in javaMail with Kotlin

I'm trying to build an email client app via javaMail with Kotlin. I used doAsync for multiThreading. But I have some problem. Getting data through the IMAP protocol is okay. When I put data into cardView, it has a problem. I used doAsync again in OnBindViewHolder to get data from javax.Message type. That was slow and not show full data into card View. -> Help me <--
This is adapter
import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.View.*
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import g2sysnet.smart_gw.R
import g2sysnet.smart_gw.inters.EventChanger
import kotlinx.android.synthetic.main.mail_reciever_row.view.*
import org.jetbrains.anko.custom.async
import org.jetbrains.anko.doAsync
import java.text.SimpleDateFormat
import javax.mail.Message
import javax.mail.internet.InternetAddress
class testAdapter (val context : Context, val receiveMessage : Array<Message> ,val eventChange : EventChanger):
RecyclerView.Adapter<testAdapter.ViewHolder>(){
#SuppressLint("SimpleDateFormat")
override fun onBindViewHolder(holder : ViewHolder, position: Int) {
val message = receiveMessage[position]
/** visibility **/
holder.itemView.d3p.visibility = INVISIBLE
holder.itemView.imV_attach.visibility = INVISIBLE
doAsync{
val from = message.from[0].toString().split("<")[0]
val subject = message.subject
val receivedDate = SimpleDateFormat("MMM dd").format(message.receivedDate)
val content = message.content.toString()
val seen = message.flags.toString()
/** unchangeable **/
holder.itemView.dateTime.text = receivedDate
holder.itemView.mailSender.text = from
holder.itemView.subjectTxt.text = subject
holder.itemView.bodyTxt.text = content
when (seen) {
"\\Seen" -> {
holder.itemView.d3p.visibility = View.INVISIBLE
}
"\\Flagged" -> {
holder.itemView.star.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.ic_star_border
)
)
holder.itemView.star.setColorFilter(
ContextCompat.getColor(
context,
R.color.icon_tint_selected
)
)
}
"\\Flagged \\Seen" -> {
holder.itemView.star.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.ic_star_border
)
)
holder.itemView.star.setColorFilter(
ContextCompat.getColor(
context,
R.color.icon_tint_selected
)
)
holder.itemView.d3p.visibility = View.INVISIBLE
}
"" -> {
holder.itemView.d3p.visibility = View.VISIBLE
holder.itemView.star.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.ic_star_border
)
)
holder.itemView.star.setColorFilter(
ContextCompat.getColor(
context,
R.color.icon_tint_normal
)
)
}
}
}
holder.itemView.setOnClickListener {
notifyItemChanged(position)
eventChange.change(position)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.mail_reciever_row, parent, false)
return ViewHolder(view)
}
class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView)
override fun getItemCount(): Int {
return receiveMessage.size
}
}
this is main page
class MailBox : AppCompatActivity(),EventChanger, NavigationView.OnNavigationItemSelectedListener {
var adapter : mailReceiveAdapter? = null
override fun change(id: Int) {
H.curRow = id
startActivity(Intent(this#MailBox,ViewerActivity::class.java))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_mailbox)
val toolbar: Toolbar = findViewById(R.id.mailBoxToolbar)
setSupportActionBar(toolbar)
supportActionBar?.title = "Mail List"
allMail_recycler.layoutManager = LinearLayoutManager(this#MailBox)
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val toggle = ActionBarDrawerToggle(
this,
drawerLayout,
toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close
)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
navView.setNavigationItemSelectedListener(this#MailBox)
test()
}
fun test(){
val dialog = ProgressDialog(this#MailBox)
dialog.setCancelable(false)
dialog.setMessage("Loading...")
dialog.show()
doAsync {
val props = Properties()
props.setProperty("mail.debug", "true")
props.setProperty("mail.imap.port", "143")
props.setProperty("mail.imap.ssl.enable", "true")
props.setProperty("mail.imap.socketFactory.port", "993")
val session =
Session.getDefaultInstance(props, authenticator(H.currentUser!!.DC_EMAIL, H.currentUser!!.NO_MAILPWD))
val store = session.getStore("imaps")
store.connect(H.currentUser!!.DC_MAILSERVER, H.currentUser!!.DC_EMAIL, H.currentUser!!.NO_MAILPWD)
val emailFolder = store.getFolder("Inbox")
emailFolder.open(Folder.READ_ONLY)
val messages: Array<Message> = emailFolder.messages
activityUiThread {
val adapter = testAdapter(this#MailBox,messages,this#MailBox)
allMail_recycler.adapter = adapter
dialog.dismiss()
}
}
}
override fun onBackPressed() {
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START)
} else {
super.onBackPressed()
}
}
}
I face this
cardView with multiThreading (doAsync)

Categories

Resources