I'm coding a quiz app, the main problem here is when an option is clicked question is changed I want that if option is wrong question remain same option become red..
class Level1 : AppCompatActivity(),View.OnClickListener {
lateinit var binding: ActivityLevel1Binding
var mQuestionList=QuestionsAndAnswer.getQuestions()
lateinit var imageView: ImageView
private var mCurrentPosition: Int = 0 // this question in model class//
private var mSelectedOptionPostion: Int = 0 // this is current option where user clicked for answer///
lateinit var progress:ProgressBar
private lateinit var tvOptionOne:TextView
private lateinit var tvOptionTwo:TextView
private lateinit var tvOptionThree:TextView
private lateinit var tvOptionFour:TextView
lateinit var progressBar: ProgressBar
lateinit var tvProgressBar: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityLevel1Binding.inflate(layoutInflater)
setContentView(binding.root)
mQuestionList=QuestionsAndAnswer.getQuestions()
setQuestion()
binding.tvOptionFour.setOnClickListener(this)
binding.tvOptionThree.setOnClickListener (this)
binding.tvOptionTwo.setOnClickListener (this)
binding.tvOptionOne.setOnClickListener (this)
binding.progressBar
}
private fun setQuestion() {
setDefault()
imageView=binding.quesImage
binding.apply {
val questions= mQuestionList[mCurrentPosition]
progressBar.progress = mCurrentPosition
tvProgressBar.text = "$mCurrentPosition" + "/" + progressBar.max
binding.quesImage.setImageResource(questions.image)
tvOptionOne.text = questions.optionOne
tvOptionTwo.text = questions.optionTwo
tvOptionThree.text = questions.optionThree
tvOptionFour.text = questions.optionFour
}
}
override fun onClick(v: View?) {
when(v?.id){
R.id.tvOptionOne->{
Selected(1,binding.tvOptionOne)
if( mCurrentPosition != mQuestionList.size-1){
mCurrentPosition ++
setQuestion()
val questions=mQuestionList?.get(mCurrentPosition -1)
if (questions?.correctAnswer!=mSelectedOptionPostion){
AnswerView(mSelectedOptionPostion,R.drawable.wrong_answer)
}
else {
AnswerView(mSelectedOptionPostion,R.drawable.correct_answer)
}
}
else {
val intent=Intent(this#Level1,ScoringActivity::class.java)
startActivity(intent)
finish()
}
}
R.id.tvOptionTwo->{
Selected(2,binding.tvOptionTwo)
if( mCurrentPosition != mQuestionList.size-1){
mCurrentPosition ++
setQuestion()
val questions=mQuestionList?.get(mCurrentPosition -1)
if (questions?.correctAnswer!=mSelectedOptionPostion){
AnswerView(mSelectedOptionPostion,R.drawable.wrong_answer)
mCurrentPosition
Toast.makeText(this,"wrong answer",Toast.LENGTH_SHORT).show()
}
AnswerView(mSelectedOptionPostion,R.drawable.correct_answer)
}
else {
val intent=Intent(this#Level1,ScoringActivity::class.java)
startActivity(intent)
finish()
}
}
R.id.tvOptionThree->{
Selected(3,binding.tvOptionThree)
if( mCurrentPosition != mQuestionList.size-1){
mCurrentPosition ++
setQuestion()
val questions=mQuestionList?.get(mCurrentPosition -1)
if (questions?.correctAnswer!=mSelectedOptionPostion){
AnswerView(mSelectedOptionPostion,R.drawable.wrong_answer)
Toast.makeText(this,"wrong answer",Toast.LENGTH_SHORT).show()
}
else{
AnswerView(mSelectedOptionPostion,R.drawable.correct_answer)
}
}
else {
val intent=Intent(this#Level1,ScoringActivity::class.java)
startActivity(intent)
finish()
}
}
// at last question on wrong answer click no action happens like no wrong answer drawable file is called //
R.id.tvOptionFour->{
Selected(4,binding.tvOptionFour)
if( mCurrentPosition != mQuestionList.size-1){
mCurrentPosition ++
setQuestion()
var questions=mQuestionList?.get(mCurrentPosition -1)
if (questions?.correctAnswer!=mSelectedOptionPostion){
AnswerView(mSelectedOptionPostion,R.drawable.wrong_answer)
}
else {
AnswerView(mSelectedOptionPostion,R.drawable.correct_answer)
}
}
else {
val intent=Intent(this#Level1,ScoringActivity::class.java)
startActivity(intent)
finish()
}
}
}
}
// here answers are maatched //
private fun AnswerView(answer: Int, drawAbleView: Int) {
when (answer) {
1 -> {
binding.tvOptionOne.background = ContextCompat.getDrawable(this, drawAbleView)
}
2 -> {
binding.tvOptionTwo.background = ContextCompat.getDrawable(this, drawAbleView)
}
3 -> {
binding.tvOptionThree.background = ContextCompat.getDrawable(this, drawAbleView)
}
4 -> {
binding.tvOptionFour.background = ContextCompat.getDrawable(this, drawAbleView)
}
}
}
private fun Selected(selected: Int, tv: TextView) {
setDefault()
mSelectedOptionPostion = selected
tv.setTextColor(Color.parseColor("#FF03DAC5"))
tv.setTypeface(tv.typeface, Typeface.BOLD)
tv.background = ContextCompat.getDrawable(this,
R.drawable.selected_tex_view)
}
private fun setDefault() {
val options = ArrayList<TextView>()
options.add(0, binding.tvOptionOne)
options.add(1, binding.tvOptionTwo)
options.add(2, binding.tvOptionThree)
options.add(3, binding.tvOptionFour)
for (option in options) {
option.setTextColor(Color.parseColor("#FF03DAC5"))
option.typeface = Typeface.DEFAULT
option.background = ContextCompat.getDrawable(this, R.drawable.round_text_view)
}
}
}
Try to change your onClick logic like this:
Note that I've declared a couple of methods to avoid code duplication
override fun onClick(v: View?) {
when(v?.id){
R.id.tvOptionOne->{
Selected(1, binding.tvOptionOne)
if(mCurrentPosition < mQuestionList.size){
setQuestion()
checkQuestion()
}
else startScoreActivity()
}
R.id.tvOptionTwo->{
Selected(2,binding.tvOptionTwo)
if(mCurrentPosition < mQuestionList.size){
setQuestion()
checkQuestion()
}
else startScoreActivity()
}
R.id.tvOptionThree->{
Selected(3,binding.tvOptionThree)
if( mCurrentPosition < mQuestionList.size){
setQuestion()
checkQuestion()
}
else startScoreActivity()
}
R.id.tvOptionFour->{
Selected(4,binding.tvOptionFour)
if( mCurrentPosition < mQuestionList.size) {
setQuestion()
}
else startScoreActivity()
}
}
}
private fun checkQuestion() {
var questions=mQuestionList?.get(mCurrentPosition)
if (questions?.correctAnswer!=mSelectedOptionPostion){
AnswerView(mSelectedOptionPostion,R.drawable.wrong_answer)
}
else {
AnswerView(mSelectedOptionPostion,R.drawable.correct_answer)
mCurrentPosition++
}
}
private fun startScoreActivity() {
val intent=Intent(this#Level1,ScoringActivity::class.java)
startActivity(intent)
finish()
}
I guess you should try moving
if (questions?.correctAnswer!=mSelectedOptionPostion) {
AnswerView(mSelectedOptionPostion,R.drawable.wrong_answer)
} else {
mCurrentPosition ++
setQuestion()
AnswerView(mSelectedOptionPostion,R.drawable.correct_answer)
}
Related
I just noticed problem earlier in my app, I see the ViewModel inside fragment doesn't save/keep recycler view when I rotate the device, I don't want to use the old method like save data in bundle onSaveInstanceState and restore it, I tried to figure why this problem by printing some logs on each method in fragment lifecycle but I didn't succeed
GIF showing the problem
the ViewModel
#HiltViewModel
class PostViewModel #Inject constructor(
private val mainRepository: MainRepository,
private val dataStoreRepository: DataStoreRepository,
application: Application
) :
AndroidViewModel(application) {
/** ROOM DATABASE */
val readAllPosts: LiveData<List<Item>> = mainRepository.localDataSource.getAllItems().asLiveData()
val postsBySearchInDB: MutableLiveData<List<Item>> = MutableLiveData()
/** RETROFIT **/
var postsResponse: MutableLiveData<NetworkResult<PostList>> = MutableLiveData()
var searchedPostsResponse: MutableLiveData<NetworkResult<PostList>> = MutableLiveData()
var postListResponse: PostList? = null
var postListByLabelResponse: PostList? = null
var searchPostListResponse: PostList? = null
val label = MutableLiveData<String>()
var finalURL: MutableLiveData<String?> = MutableLiveData()
val token = MutableLiveData<String?>()
val currentDestination = MutableLiveData<Int>()
fun getCurrentDestination() {
viewModelScope.launch {
dataStoreRepository.readCurrentDestination.collect {
currentDestination.value = it
}
}
}
val errorCode = MutableLiveData<Int>()
val searchError = MutableLiveData<Boolean>()
var networkStats = false
var backOnline = false
val recyclerViewLayout = dataStoreRepository.readRecyclerViewLayout.asLiveData()
val readBackOnline = dataStoreRepository.readBackOnline.asLiveData()
override fun onCleared() {
super.onCleared()
finalURL.value = null
token.value = null
}
private fun saveBackOnline(backOnline: Boolean) = viewModelScope.launch {
dataStoreRepository.saveBackOnline(backOnline)
}
fun saveCurrentDestination(currentDestination: Int) {
viewModelScope.launch {
dataStoreRepository.saveCurrentDestination(currentDestination)
}
}
fun saveRecyclerViewLayout(layout: String) {
viewModelScope.launch {
dataStoreRepository.saveRecyclerViewLayout(layout)
}
}
fun getPosts() = viewModelScope.launch {
getPostsSafeCall()
}
fun getPostListByLabel() = viewModelScope.launch {
getPostsByLabelSafeCall()
}
fun getItemsBySearch() = viewModelScope.launch {
getItemsBySearchSafeCall()
}
private suspend fun getPostsByLabelSafeCall() {
postsResponse.value = NetworkResult.Loading()
if (hasInternetConnection()) {
try {
val response = mainRepository.remoteDataSource.getPostListByLabel(finalURL.value!!)
postsResponse.value = handlePostsByLabelResponse(response)
} catch (ex: HttpException) {
Log.e(TAG, ex.message + ex.cause)
postsResponse.value = NetworkResult.Error(ex.message.toString())
errorCode.value = ex.code()
} catch (ex: NullPointerException) {
postsResponse.value = NetworkResult.Error("There's no items")
}
} else {
postsResponse.value = NetworkResult.Error("No Internet Connection.")
}
}
private suspend fun getPostsSafeCall() {
postsResponse.value = NetworkResult.Loading()
if (hasInternetConnection()) {
try {
if (finalURL.value.isNullOrEmpty()) {
finalURL.value = "$BASE_URL?key=$API_KEY"
}
val response = mainRepository.remoteDataSource.getPostList(finalURL.value!!)
postsResponse.value = handlePostsResponse(response)
} catch (e: Exception) {
postsResponse.value = NetworkResult.Error(e.message.toString())
if (e is HttpException) {
errorCode.value = e.code()
Log.e(TAG, "getPostsSafeCall: errorCode $errorCode")
Log.e(TAG, "getPostsSafeCall: ${e.message.toString()}")
}
}
} else {
postsResponse.value = NetworkResult.Error("No Internet Connection.")
}
}
private fun handlePostsResponse(response: Response<PostList>): NetworkResult<PostList> {
if (response.isSuccessful) {
if (!(token.value.equals(response.body()?.nextPageToken))) {
token.value = response.body()?.nextPageToken
response.body()?.let { resultResponse ->
Log.d(
TAG, "handlePostsResponse: old token is: ${token.value} " +
"new token is: ${resultResponse.nextPageToken}"
)
finalURL.value = "${BASE_URL}?pageToken=${token.value}&key=${API_KEY}"
Log.e(TAG, "handlePostsResponse finalURL is ${finalURL.value!!}")
for (item in resultResponse.items) {
insertItem(item)
}
return NetworkResult.Success(resultResponse)
}
}
}
if (token.value == null) {
errorCode.value = 400
} else {
errorCode.value = response.code()
}
return NetworkResult.Error(
"network results of handlePostsResponse ${
response.body().toString()
}"
)
}
private fun handlePostsByLabelResponse(response: Response<PostList>): NetworkResult<PostList> {
if (response.isSuccessful) {
response.body()?.let { resultResponse ->
Log.d(
TAG, "handlePostsByLabelResponse: old token is: ${token.value} " +
"new token is: ${resultResponse.nextPageToken}"
)
finalURL.postValue(
(BASE_URL_POSTS_BY_LABEL + "posts?labels=${label.value}"
+ "&maxResults=20"
+ "&pageToken=")
+ token.value
+ "&key=" + API_KEY
)
if (postListByLabelResponse == null) {
postListByLabelResponse = resultResponse
} else {
val oldPosts = postListByLabelResponse?.items
val newPosts = resultResponse.items
oldPosts?.addAll(newPosts)
}
return NetworkResult.Success(postListByLabelResponse?:resultResponse)
}
}
if (token.value == null) {
errorCode.value = 400
} else {
errorCode.value = response.code()
}
Log.e(TAG, "handlePostsByLabelResponse: final URL ${finalURL.value}")
return NetworkResult.Error(
"network results of handlePostsByLabelResponse ${
response.body().toString()
}"
)
}
private fun hasInternetConnection(): Boolean {
val connectivityManager = getApplication<Application>().getSystemService(
Context.CONNECTIVITY_SERVICE
) as ConnectivityManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val activeNetwork = connectivityManager.activeNetwork ?: return false
val capabilities =
connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false
return when {
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN) -> true
else -> false
}
} else {
val networkInfo = connectivityManager.activeNetworkInfo
return networkInfo != null && networkInfo.isConnectedOrConnecting
}
}
fun showNetworkStats() {
if (!networkStats) {
Toast.makeText(getApplication(), "No Internet connection", Toast.LENGTH_SHORT).show()
saveBackOnline(true)
} else if (networkStats) {
if (backOnline) {
Toast.makeText(getApplication(), "We're back online", Toast.LENGTH_SHORT).show()
saveBackOnline(false)
}
}
}
private fun insertItem(item: Item) {
viewModelScope.launch(Dispatchers.IO) {
mainRepository.localDataSource.insertItem(item)
}
}
private suspend fun getItemsBySearchSafeCall() {
searchedPostsResponse.value = NetworkResult.Loading()
if (!label.value.isNullOrEmpty()) {
finalURL.value = "${BASE_URL}?labels=${label.value}&maxResults=500&key=$API_KEY"
}
Log.e(TAG, "getItemsBySearch: ${finalURL.value}")
if (hasInternetConnection()) {
try {
val response = mainRepository.remoteDataSource.getPostListBySearch(finalURL.value!!)
searchedPostsResponse.value = handlePostsBySearchResponse(response)
} catch (e: Exception) {
searchedPostsResponse.value = NetworkResult.Error(e.message.toString())
}
} else {
searchedPostsResponse.value = NetworkResult.Error("No Internet Connection.")
}
}
private fun handlePostsBySearchResponse(response: Response<PostList>): NetworkResult<PostList> {
return if (response.isSuccessful) {
val postListResponse = response.body()
NetworkResult.Success(postListResponse!!)
} else {
errorCode.value = response.code()
NetworkResult.Error(response.errorBody().toString())
}
}
fun getItemsBySearchInDB(keyword: String) {
Log.d(TAG, "getItemsBySearchInDB: called")
viewModelScope.launch {
val items = mainRepository.localDataSource.getItemsBySearch(keyword)
if (items.isNotEmpty()) {
postsBySearchInDB.value = items
} else {
searchError.value = true
Log.e(TAG, "list is empty")
}
}
}
}
the fragment
#AndroidEntryPoint
class AccessoryFragment : Fragment(), MenuProvider, TitleAndGridLayout {
private var _binding: FragmentAccessoryBinding? = null
private val binding get() = _binding!!
private var searchItemList = arrayListOf<Item>()
private lateinit var postViewModel: PostViewModel
private val titleLayoutManager: GridLayoutManager by lazy { GridLayoutManager(context, 2) }
private val gridLayoutManager: GridLayoutManager by lazy { GridLayoutManager(context, 3) }
private var linearLayoutManager: LinearLayoutManager? = null
private val KEY_RECYCLER_STATE = "recycler_state"
private val mBundleRecyclerViewState by lazy { Bundle() }
private lateinit var adapter: PostAdapter
private var isScrolling = false
var currentItems = 0
var totalItems: Int = 0
var scrollOutItems: Int = 0
private var postsAPiFlag = false
private var keyword: String? = null
private lateinit var networkListener: NetworkListener
private var networkStats = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
postViewModel = ViewModelProvider(this)[PostViewModel::class.java]
adapter = PostAdapter(this)
postViewModel.finalURL.value =
BASE_URL_POSTS_BY_LABEL + "posts?labels=Accessory&maxResults=20&key=$API_KEY"
networkListener = NetworkListener()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentAccessoryBinding.inflate(inflater, container, false)
val menuHost: MenuHost = requireActivity()
menuHost.addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.CREATED)
postViewModel.label.value = "Accessory"
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Log.d(TAG, "onViewCreated: called")
postViewModel.recyclerViewLayout.observe(viewLifecycleOwner) { layout ->
linearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
Log.w(TAG, "onViewCreated getSavedLayout called")
when (layout) {
"cardLayout" -> {
binding.accessoryRecyclerView.layoutManager = linearLayoutManager
adapter.viewType = 0
binding.accessoryRecyclerView.adapter = adapter
}
"cardMagazineLayout" -> {
binding.accessoryRecyclerView.layoutManager = linearLayoutManager
adapter.viewType = 1
binding.accessoryRecyclerView.adapter = adapter
}
"titleLayout" -> {
binding.accessoryRecyclerView.layoutManager = titleLayoutManager
adapter.viewType = 2
binding.accessoryRecyclerView.adapter = adapter
}
"gridLayout" -> {
binding.accessoryRecyclerView.layoutManager = gridLayoutManager
adapter.viewType = 3
binding.accessoryRecyclerView.adapter = adapter
}
}
}
lifecycleScope.launchWhenStarted {
networkListener.checkNetworkAvailability(requireContext()).collect { stats ->
Log.d(TAG, "networkListener: $stats")
postViewModel.networkStats = stats
postViewModel.showNetworkStats()
this#AccessoryFragment.networkStats = stats
if (stats ) {
if (binding.accessoryRecyclerView.visibility == View.GONE) {
binding.accessoryRecyclerView.visibility = View.VISIBLE
}
requestApiData()
} else {
// Log.d(TAG, "onViewCreated: savedInstanceState $savedInstanceState")
noInternetConnectionLayout()
}
}
}
binding.accessoryRecyclerView.onItemClick { _, position, _ ->
val postItem = adapter.differ.currentList[position]
findNavController().navigate(
AccessoryFragmentDirections.actionNavAccessoryToDetailsActivity(
postItem
)
)
}
binding.accessoryRecyclerView.addOnScrollListener(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)
currentItems = linearLayoutManager!!.childCount
totalItems = adapter.itemCount
scrollOutItems = linearLayoutManager!!.findFirstVisibleItemPosition()
if ((!recyclerView.canScrollVertically(1) && dy > 0) &&
(isScrolling && currentItems + scrollOutItems >= totalItems && postsAPiFlag)
) {
hideShimmerEffect()
postViewModel.getPostListByLabel()
isScrolling = false
}
}
})
postViewModel.errorCode.observe(viewLifecycleOwner) { errorCode ->
if (errorCode == 400) {
binding.accessoryRecyclerView.setPadding(0, 0, 0, 0)
Toast.makeText(requireContext(), R.string.lastPost, Toast.LENGTH_LONG).show()
binding.progressBar.visibility = View.GONE
} else {
Log.e(TAG, "onViewCreated: ${postViewModel.errorCode.value.toString()} ")
noInternetConnectionLayout()
}
}
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
Log.d(TAG, "onConfigurationChanged: ${newConfig.orientation}")
Log.d(TAG, "onConfigurationChanged: ${adapter.differ.currentList.toString()}")
Log.d(
TAG,
"onConfigurationChanged: " +
binding.accessoryRecyclerView.layoutManager?.itemCount.toString()
)
}
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
Log.d(TAG, "onViewStateRestored: called")
}
private fun requestApiData() {
showShimmerEffect()
Log.d(TAG, "requestApiData: called")
postViewModel.getPostListByLabel()
postViewModel.postsResponse.observe(viewLifecycleOwner) { response ->
postsAPiFlag = true
when (response) {
is NetworkResult.Success -> {
hideShimmerEffect()
response.data?.let {
binding.progressBar.visibility = View.GONE
// itemArrayList.addAll(it.items)
adapter.differ.submitList(it.items.toList())
}
}
is NetworkResult.Error -> {
hideShimmerEffect()
binding.progressBar.visibility = View.GONE
Log.e(TAG, response.data.toString())
Log.e(TAG, response.message.toString())
}
is NetworkResult.Loading -> {
binding.progressBar.visibility = View.VISIBLE
}
}
}
}
private fun showShimmerEffect() {
binding.apply {
shimmerLayout.visibility = View.VISIBLE
accessoryRecyclerView.visibility = View.INVISIBLE
}
}
private fun hideShimmerEffect() {
binding.apply {
shimmerLayout.stopShimmer()
shimmerLayout.visibility = View.GONE
accessoryRecyclerView.visibility = View.VISIBLE
}
}
private fun changeAndSaveLayout() {
Log.w(TAG, "changeAndSaveLayout: called")
val builder = AlertDialog.Builder(requireContext())
builder.setTitle(getString(R.string.choose_layout))
val recyclerViewLayouts = resources.getStringArray(R.array.RecyclerViewLayouts)
// SharedPreferences.Editor editor = sharedPreferences.edit();
builder.setItems(
recyclerViewLayouts
) { _: DialogInterface?, index: Int ->
try {
when (index) {
0 -> {
adapter.viewType = 0
binding.accessoryRecyclerView.layoutManager = linearLayoutManager
binding.accessoryRecyclerView.adapter = adapter
postViewModel.saveRecyclerViewLayout("cardLayout")
}
1 -> {
adapter.viewType = 1
binding.accessoryRecyclerView.layoutManager = linearLayoutManager
binding.accessoryRecyclerView.adapter = adapter
postViewModel.saveRecyclerViewLayout("cardMagazineLayout")
}
2 -> {
adapter.viewType = 2
binding.accessoryRecyclerView.layoutManager = titleLayoutManager
binding.accessoryRecyclerView.adapter = adapter
postViewModel.saveRecyclerViewLayout("titleLayout")
}
3 -> {
adapter.viewType = 3
binding.accessoryRecyclerView.layoutManager = gridLayoutManager
binding.accessoryRecyclerView.adapter = adapter
postViewModel.saveRecyclerViewLayout("gridLayout")
}
}
} catch (e: Exception) {
Log.e(TAG, "changeAndSaveLayout: " + e.message)
Log.e(TAG, "changeAndSaveLayout: " + e.cause)
}
}
val alertDialog = builder.create()
alertDialog.show()
}
private fun noInternetConnectionLayout() {
binding.apply {
// accessoryRecyclerView.removeAllViews()
Log.d(TAG, "noInternetConnectionLayout: called")
shimmerLayout.stopShimmer()
shimmerLayout.visibility = View.GONE
accessoryRecyclerView.visibility = View.GONE
}
binding.noInternetConnectionLayout.inflate()
binding.noInternetConnectionLayout.let {
if (networkStats) {
it.visibility = View.GONE
}
}
}
override fun onDestroyView() {
super.onDestroyView()
// adapter.isDestroyed = true
linearLayoutManager?.removeAllViews()
// adView.destroy()
linearLayoutManager = null
_binding = null
}
override fun onDetach() {
super.onDetach()
if(linearLayoutManager != null){
linearLayoutManager = null
}
}
override fun tellFragmentToGetItems() {
if (postViewModel.recyclerViewLayout.value.equals("titleLayout")
|| postViewModel.recyclerViewLayout.value.equals("gridLayout")
) {
hideShimmerEffect()
postViewModel.getPostListByLabel()
}
}
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.main, menu)
val searchManager =
requireContext().getSystemService(Context.SEARCH_SERVICE) as SearchManager
val searchView = menu.findItem(R.id.app_bar_search).actionView as SearchView
searchView.setSearchableInfo(searchManager.getSearchableInfo(requireActivity().componentName))
searchView.queryHint = resources.getString(R.string.searchForPosts)
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(keyword: String): Boolean {
if (keyword.isEmpty()) {
Snackbar.make(
requireView(),
"please enter keyword to search",
Snackbar.LENGTH_SHORT
).show()
}
// itemArrayList.clear()
this#AccessoryFragment.keyword = keyword
requestSearchApi(keyword)
return false
}
override fun onQueryTextChange(newText: String): Boolean {
return false
}
})
searchView.setOnCloseListener {
if (keyword.isNullOrEmpty()) {
hideShimmerEffect()
return#setOnCloseListener false
}
if (Utils.hasInternetConnection(requireContext())) {
showShimmerEffect()
postViewModel.postListByLabelResponse = null
searchItemList.clear()
// adapter.differ.submitList(ArrayList())
linearLayoutManager?.removeAllViews()
binding.accessoryRecyclerView.removeAllViews()
// itemArrayList.clear()
adapter.differ.submitList(null)
postViewModel.finalURL.value =
BASE_URL_POSTS_BY_LABEL + "posts?labels=Accessory&maxResults=20&key=$API_KEY"
requestApiData()
// itemArrayList.clear()
// adapter.submitList(itemArrayList)
//====> Here I call the request api method again
Log.d(
TAG,
"setOnCloseListener: called ${adapter.differ.currentList.size.toString()}"
)
// adapter.notifyDataSetChanged()
// binding.progressBar.visibility = View.GONE
//
Log.d(TAG, "setOnCloseListener: ${postViewModel.finalURL.value.toString()}")
//
// adapter.notifyDataSetChanged()
// }
} else {
Log.d(TAG, "setOnCloseListener: called")
adapter.differ.submitList(null)
searchItemList.clear()
noInternetConnectionLayout()
}
false
}
postViewModel.searchError.observe(viewLifecycleOwner) { searchError ->
if (searchError) {
Toast.makeText(
requireContext(),
"There's no posts with this keyword", Toast.LENGTH_LONG
).show()
}
}
}
private fun requestSearchApi(keyword: String) {
if (Utils.hasInternetConnection(requireContext())) {
showShimmerEffect()
postViewModel.finalURL.value =
"${BASE_URL}?labels=Accessory&maxResults=500&key=$API_KEY"
postViewModel.getItemsBySearch()
postViewModel.searchedPostsResponse.observe(viewLifecycleOwner) { response ->
when (response) {
is NetworkResult.Success -> {
postsAPiFlag = false
// adapter.differ.currentList.clear()
if (searchItemList.isNotEmpty()) {
searchItemList.clear()
}
binding.progressBar.visibility = View.GONE
lifecycleScope.launch {
withContext(Dispatchers.Default) {
searchItemList.addAll(response.data?.items?.filter {
it.title.contains(keyword) || it.content.contains(keyword)
} as ArrayList<Item>)
}
}
Log.d(TAG, "requestSearchApi: test size ${searchItemList.size}")
if (searchItemList.isEmpty()) {
// adapter.differ.submitList(null)
Toast.makeText(
requireContext(),
"The search word was not found in any post",
Toast.LENGTH_SHORT
).show()
hideShimmerEffect()
return#observe
} else {
postsAPiFlag = false
// itemArrayList.clear()
adapter.differ.submitList(null)
hideShimmerEffect()
// Log.d(
//// TAG, "requestSearchApi: searchItemList ${searchItemList[0].title}"
// )
adapter.differ.submitList(searchItemList)
// binding.accessoryRecyclerView.scrollToPosition(0)
}
}
is NetworkResult.Error -> {
hideShimmerEffect()
binding.progressBar.visibility = View.GONE
Toast.makeText(
requireContext(),
response.message.toString(),
Toast.LENGTH_SHORT
).show()
Log.e(TAG, "onQueryTextSubmit: $response")
}
is NetworkResult.Loading -> {
binding.progressBar.visibility = View.VISIBLE
}
}
}
} else {
noInternetConnectionLayout()
}
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return if (menuItem.itemId == R.id.change_layout) {
changeAndSaveLayout()
true
} else false
}
}
Unless I'm missing something (that's a lot of code to go through!) you don't set any data on your adapter until this bit:
private fun requestApiData() {
postViewModel.getPostListByLabel()
postViewModel.postsResponse.observe(viewLifecycleOwner) {
...
adapter.differ.submitList(it.items.toList())
}
And getPostListByLabel() clears the current data in postsResponse
fun getPostListByLabel() = viewModelScope.launch {
getPostsByLabelSafeCall()
}
private suspend fun getPostsByLabelSafeCall() {
postsResponse.value = NetworkResult.Loading()
// fetch data over network and update postsResponse with it later
...
}
So when you first observe it, it's in the NetworkResult.Loading state - any posts you had stored have been wiped.
Your Fragment gets recreated when the Activity is rotated and destroyed - so if you're initialising the ViewModel data contents as part of that Fragment setup (like you're doing here) it's going to get reinitialised every time the Fragment is recreated, and you'll lose the current data.
You'll need to work out a way to avoid that happening - you don't actually want to do that clear-and-fetch whenever a Fragment is created, so you'll have to decide when it should happen. Maybe when the ViewModel is first created (i.e. through the init block), maybe the first time a Fragment calls it (e.g. create an initialised boolean in the VM set to false, check it in the call, set true when it runs). Or maybe just when postsResponse has no value yet (postsResponse.value == null). I don't know the flow of your application so you'll have to work out when to force a fetch and when to keep the data that's already there
I'm having problem with my step counter, I want it to reset to 0 every time the date changes.
I tried doing something like this:
if (currentDate != savedDate) {
previousSteps = totalSteps
tv_totalSteps.text = 0.toString()
saveData()
}
but I just couldn't seem to get it to work for some reason. I'm sure the answer is obvious somewhere in my code, but I've been trying different things for about 2 hours now. So any help would be very much appreciated here. Here's my whole code:
private var sensorManager: SensorManager? = null
private var running = false
private var totalSteps = 0f
private var previousSteps = 0f
var currentSteps = 0
var goalSteps = 5000
private var cal = Calendar.getInstance()
private var currentDate = cal.get(Calendar.DAY_OF_YEAR)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//needs to be called later
loadData()
resetSteps()
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
}
override fun onResume() {
super.onResume()
running = true
val stepsSensor = sensorManager?.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
if (stepsSensor == null) {
Toast.makeText(this, "No sensor detected", Toast.LENGTH_SHORT).show()
} else {
sensorManager?.registerListener(this, stepsSensor, SensorManager.SENSOR_DELAY_UI)
}
}
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {
}
override fun onSensorChanged(event: SensorEvent) {
if (running) {
totalSteps = event.values[0]
currentSteps = totalSteps.toInt() - previousSteps.toInt()
tv_totalSteps.text = ("$currentSteps")
progress_circular.apply {
setProgressWithAnimation(currentSteps.toFloat())
}
progress_circular_outer_ring.apply {
setProgressWithAnimation(totalSteps)
}
val caloriesBurned = totalSteps * .0228f
tv_calories.text = "${caloriesBurned.toInt()} calories"
tv_distance_walked.text = "${currentSteps} steps"
tv_totalDistanceWalked.text = "${(totalSteps* 0.00076f).toInt()} km"
tv_totalStepsTaken.text = "${totalSteps.toInt()} steps"
progress_circular_calories.apply {
setProgressWithAnimation(caloriesBurned)
}
}
}
private fun resetSteps() {
tv_totalSteps.setOnClickListener {
Toast.makeText(this, "Long hold to reset steps", Toast.LENGTH_SHORT).show()
}
tv_totalSteps.setOnLongClickListener {
previousSteps = totalSteps
tv_totalSteps.text = 0.toString()
saveData()
true
}
tv_totalStepsMax.setOnClickListener {
tv_totalStepsMax.visibility = View.GONE
et_totalStepsMax.visibility = View.VISIBLE
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(et_totalStepsMax, 0)
}
rL_wrapper.setOnClickListener {
tv_totalStepsMax.visibility = View.VISIBLE
et_totalStepsMax.visibility = View.GONE
if (et_totalStepsMax.text != null && et_totalStepsMax.text.toString().isNotEmpty()) {
goalSteps = Integer.parseInt(et_totalStepsMax.text.toString())
tv_totalStepsMax.text = goalSteps.toString()
progress_circular.progressMax = goalSteps.toFloat()
saveData()
} else {
return#setOnClickListener
}
val inputMethodManager =
getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(et_totalStepsMax.windowToken, 0)
}
}
override fun onPause() {
super.onPause()
saveData()
}
private fun saveData() {
val sharedPreferences = getSharedPreferences("myPrefs", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.putFloat("key1", previousSteps)
editor.putInt("goalKey", goalSteps)
editor.putInt("DATE_KEY", currentDate)
Log.d("MainActivity", "Today is $currentDate")
editor.apply()
}
private fun loadData() {
val sharedPreferences = getSharedPreferences("myPrefs", Context.MODE_PRIVATE)
val savedNumber = sharedPreferences.getFloat("key1", 0f)
val goalNumber = sharedPreferences.getInt("goalKey", 0)
val savedDate = sharedPreferences.getInt("DATE_KEY", 0)
Log.d("MainActivity", "Saved date is $savedDate")
if (currentDate != savedDate) {
previousSteps = totalSteps
tv_totalSteps.text = 0.toString()
saveData()
}
Log.d("MainActivity", "$savedNumber")
goalSteps = goalNumber
tv_totalStepsMax.text = goalSteps.toString()
previousSteps = savedNumber
}
}
You are just rewriting tv_totalStepsMax.text = goalSteps.toString() after resetting the value tv_totalSteps.text = 0.toString().
The code should look like:
if (currentDate != savedDate) {
tv_totalSteps.text = 0.toString()
...
saveData()
} else {
tv_totalStepsMax.text = goalSteps.toString()
...
}
I have two screens first one has recycler view list of data and searchView above it that's filter data in this recycler, the view Model code of the first fragment
class MscInspectionViewModel(val activity: LaunchActivity, val mRootView: MscInspectFragment) :
BaseViewModel(),
SwipeRefreshLayout.OnRefreshListener {
val toolBarTitle: MutableLiveData<String> = MutableLiveData()
private val getDataError = MutableLiveData<Boolean>()
var listType = MutableLiveData<Int>()
val hint = MutableLiveData<String>()
private var isRefreshing: Boolean = false
private var mSharedPreferences: SharedPreferences? = null
val dataListAdapter = ContainersUnderCheckAdapter(activity)
val backClickListener = View.OnClickListener { activity.supportFragmentManager.popBackStack() }
val filterDataByTab = object : TabLayout.OnTabSelectedListener {
override fun onTabReselected(tab: TabLayout.Tab?) {
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
}
override fun onTabSelected(tab: TabLayout.Tab?) {
when (tab!!.text) {
activity.resources.getString(R.string.cidPending) -> {
listType.value = 0
getPendingData()
}
activity.resources.getString(R.string.cidDone) -> {
listType.value = 1
getDoneData()
}
}
}
}
val filterData = object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
if (query.length > 2) {
val mQuery = Utility(activity).switchArabicNumerals(query)
dataListAdapter.getFilter(3, listType.value!!).filter(mQuery)
} else {
errorMessage.value = activity.resources.getString(R.string.addCorrectNumber)
}
return true
}
override fun onQueryTextChange(newText: String): Boolean {
if (newText.length > 2) {
val mQuery = Utility(activity).switchArabicNumerals(newText)
dataListAdapter.getFilter(3, listType.value!!).filter(mQuery)
}
return false;
}
}
val closeImgListener = View.OnClickListener {
mRootView.svSearchMSC.setQuery("", true)
if (listType.value == 1) {
dataListAdapter.getFilter(1, listType.value!!).filter("ANY")
} else if (listType.value == 0) {
dataListAdapter.getFilter(2, listType.value!!).filter("PENDING")
}
}
init {
listType.value = 0
mSharedPreferences = getDefaultSharedPreferences(activity.applicationContext)
toolBarTitle.value = activity.resources.getString(R.string.mscInspectTitle)
hint.value = activity.resources.getString(R.string.msc_search)
getData()
}
fun getData() {
onRetrievePostListStart()
subscription = apiAccount.getContainersUnderCheck(
"getContainersUnderCheck",
mSharedPreferences!!.getString(Constants.CFID, "")!!,
mSharedPreferences!!.getString(Constants.CFTOKEN, "")!!
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe {}
.doOnTerminate {}
.subscribe({ result ->
result?.let {
if (result.ResponseCode != null && result.ResponseCode.trim() != "000") {
onRetrievePostListError(result.ResponseMessage)
} else {
result.ContainersData?.let { it1 -> onRetrievePostListSuccess(it1) }
}
}
}, { throwable ->
android.util.Log.e("getDataInquiry", throwable.message!!)
onRetrievePostListError(activity.resources.getString(R.string.general_error))
})
}
private fun getPendingData() {
val query = mRootView.svSearchMSC.query.toString()
if (query == "") {
dataListAdapter.getFilter(2, listType.value!!).filter("PENDING")
} else {
if (query.length > 2) {
dataListAdapter.getFilter(3, listType.value!!).filter(query)
} else {
errorMessage.value = activity.resources.getString(R.string.addCorrectNumber)
}
}
}
private fun getDoneData() {
val query = mRootView.svSearchMSC.query.toString()
if (query == "") {
dataListAdapter.getFilter(1, listType.value!!).filter("ANY")
} else {
if (query.length > 2) {
dataListAdapter.getFilter(3, listType.value!!).filter(query)
} else {
errorMessage.value = activity.resources.getString(R.string.addCorrectNumber)
}
}
}
private fun onRetrievePostListStart() {
loading.value = true
}
private fun onRetrievePostListFinish() {
loading.value = false
isRefreshing = false
}
private fun onRetrievePostListSuccess(containersData: List<ContainersData>) {
onRetrievePostListFinish()
dataListAdapter.updateInquiryAdapter(containersData as ArrayList<ContainersData>)
if (listType.value == 1) {
dataListAdapter.getFilter(1, listType.value!!).filter("ANY")
} else if (listType.value == 0) {
dataListAdapter.getFilter(2, listType.value!!).filter("PENDING")
}
}
private fun onRetrievePostListError(message: String?) {
onRetrievePostListFinish()
getDataError.value = true
errorMessage.value = message
}
override fun onCleared() {
super.onCleared()
subscription.dispose()
}
override fun onRefresh() {
isRefreshing = true
getData()
}
}
adapter is :
class ContainersUnderCheckAdapter(val activity: LaunchActivity) :
RecyclerView.Adapter<ContainersUnderCheckAdapter.ViewHolder>() {
private lateinit var mDataSet: ArrayList<ContainersData>
private lateinit var mDataSetFiltered: ArrayList<ContainersData>
fun updateInquiryAdapter(dataSet: ArrayList<ContainersData>) {
mDataSet = ArrayList()
mDataSet.clear()
mDataSet.addAll(dataSet)
mDataSetFiltered = mDataSet
getFilter(2, 1).filter("PENDING")
// notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding: ContianerItemFieldLayoutBinding = DataBindingUtil
.inflate(
LayoutInflater.from(parent.context),
R.layout.contianer_item_field_layout,
parent,
false
)
return ViewHolder(binding, activity)
}
override fun getItemCount(): Int {
return if (::mDataSetFiltered.isInitialized) mDataSetFiltered.size else 0
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(mDataSetFiltered[position])
}
operator fun get(position: Int): ContainersData {
return mDataSetFiltered.get(position)
}
/**
* #filterType :
* IF 1 : filter on Data Type RJCTD + APPROVED
* 2 : filter on Data Type PENDING
* 3 :
*/
fun getFilter(filterType: Int, listType: Int): Filter {
return object : Filter() {
override fun performFiltering(charSequence: CharSequence): FilterResults {
val charString = charSequence.toString()
mDataSetFiltered = if (charString.isEmpty()) {
mDataSet
} else {
val filteredList = ArrayList<ContainersData>()
for (row in mDataSet) {
when (filterType) {
1 -> {
if (row.status == "RJCTD" || row.status == "APPROVED") {
filteredList.add(row)
}
}
2 -> {
if (row.status == charString) {
filteredList.add(row)
}
}
3 -> {
when (listType) {
0 -> {
if ((row.CID!!.contains(charString.toUpperCase(Locale.ROOT)) || row.TN!!.contains(
charSequence
) || row.PN!!.contains(charSequence)) && row.status == "PENDING"
) {
filteredList.add(row)
}
}
1 -> {
if ((row.CID!!.contains(charString.toUpperCase(Locale.ROOT)) || row.TN!!.contains(
charSequence
) || row.PN!!.contains(charSequence)) && row.status != "PENDING"
) {
filteredList.add(row)
}
}
}
}
}
}
filteredList
}
val filterResults = FilterResults()
filterResults.values = mDataSetFiltered
return filterResults
}
override fun publishResults(
charSequence: CharSequence,
filterResults: FilterResults
) {
if (::mDataSetFiltered.isInitialized) {
mDataSetFiltered = try {
filterResults.values as ArrayList<ContainersData>
} catch (e: Exception) {
Log.e("mDataSetFiltered",e.message!!)
ArrayList()
}
when (filterType) {
1->{
mDataSetFiltered.sortWith(Comparator { p0, p1 -> p1!!.UpdateDate.compareTo(p0!!.UpdateDate) })
}
2->{
mDataSetFiltered.sortWith(Comparator { p0, p1 -> p0!!.ID!!.compareTo(p1.ID!!) })
}
}
}
// refresh the list with filtered data
notifyDataSetChanged()
}
}
}
class ViewHolder(
private val binding: ContianerItemFieldLayoutBinding,
val activity: LaunchActivity
) : RecyclerView.ViewHolder(binding.root) {
private val viewModel = MscInspectionListViewModel(activity)
fun bind(data: ContainersData) {
viewModel.bind(data)
binding.viewModel = viewModel
}
}
}
any data in this recycler on click go to fragment has tow recycler first one to show data, the second one to pick Images
the second-page code
class MSCDataFragment : Fragment() {
lateinit var rootView: View
lateinit var activity: LaunchActivity
lateinit var utility: Utility
lateinit var loadingView: LoadingView
private lateinit var viewModel: MSCDataViewModel
private lateinit var binding: FragmentMscdataBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (getActivity() != null) {
activity = getActivity() as LaunchActivity
utility = Utility(activity)
loadingView = LoadingView(activity)
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_mscdata, container, false)
rootView = binding.root
initial()
return rootView
}
private fun initial() {
viewModel = ViewModelProvider(
this, ViewModelFactory(
activity,
arguments!!.getSerializable("Data") as ContainersData
)
).get(MSCDataViewModel::class.java)
binding.viewModel = viewModel
// binding.imgList.layoutManager = GridLayoutManager(activity, 3)
binding.containerInfo.layoutManager = LinearLayoutManager(activity)
binding.openCIDNotValid.typeface =
Typeface.createFromAsset(activity.assets, "Bahij_Janna-Regular.ttf")
binding.openCIDNotValid.setOnCheckedChangeListener(viewModel.onOpenCidNotValidListener)
viewModel.loading.observe(this, Observer { loading ->
loading?.let {
if (it) {
loadingView.show()
} else {
loadingView.dismiss()
}
}
})
viewModel.errorMessage.observe(this, Observer { msg ->
msg?.let {
utility.ShowToast(msg)
}
})
viewModel.imagesAdapters2.observe(this, Observer { msg ->
msg?.let {
binding.imgList.apply {
layoutManager = GridLayoutManager(activity, 3)
adapter = it
}
}
})
rootView.toolbar_Back.setOnClickListener(viewModel.backClickListener)
binding.btnAddImages.setOnClickListener(viewModel.pickImages)
binding.successContianer.setOnClickListener(viewModel.correctContainer)
binding.damagedContianer.setOnClickListener(viewModel.wrongContainer)
}
}
the view model is :
class MSCDataViewModel(val activity: LaunchActivity, val containersData: ContainersData) :
BaseViewModel(), GetImagesListener {
#Inject
lateinit var restApiAccount: RestApiAccount
val toolBarTitle: MutableLiveData<String> = MutableLiveData()
val ButtonText: MutableLiveData<String> = MutableLiveData()
var openCIDNotValidVisibility = MutableLiveData<Int>()
private val getDataError = MutableLiveData<Boolean>()
val btnImagesVisibility = MutableLiveData<Int>()
var imgeNoteVisibility = MutableLiveData<Int>()
var successVisibility = MutableLiveData<Int>()
var damagedVisibility = MutableLiveData<Int>()
var notesVisibility = MutableLiveData<Int>()
val btnVisibility = MutableLiveData<Int>()
var canNotOpen = MutableLiveData<Int>()
private val images = ArrayList<Image>()
var utility = Utility(activity)
private var CURRENTINDEX = 0
private var mSharedPreferences: SharedPreferences? = null
val DataListAdapter = ContainerDataAdapter(activity)
var imagesAdapter = ContainerImagesAdapter(activity, containersData.status!!, ArrayList())
val imagesAdapters2 = MutableLiveData<ContainerImagesAdapter2>()
val userInfo: UserInfo
val backClickListener = View.OnClickListener { activity.supportFragmentManager.popBackStack() }
val pickImages = View.OnClickListener {
pickImages()
}
val correctContainer = View.OnClickListener {}
val onOpenCidNotValidListener =
CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
successVisibility.value = View.GONE
canNotOpen.value = 1
} else {
canNotOpen.value = 0
successVisibility.value = View.VISIBLE
}
}
val wrongContainer = View.OnClickListener {}
var mscNotes: ObservableField<String> = ObservableField("")
init {
canNotOpen.value = 0
mSharedPreferences =
PreferenceManager.getDefaultSharedPreferences(activity.applicationContext)
toolBarTitle.value = containersData.CID
ButtonText.value = activity.resources.getString(R.string.cleanContianer)
userInfo = utility.readObjectFromSharedPreferences(
mSharedPreferences,
Constants.USER_INFO_KEY,
UserInfo::class.java
) as UserInfo
openCIDNotValidVisibility.value = View.GONE
fillData()
}
private fun fillData() {
val data: LinkedHashMap<String, String> = containersData.data!!
val captionsMap = utility.readObjectFromSharedPreferences(
mSharedPreferences, Constants.CAPTIONS_MAP_KEY,
HashMap::class.java
) as HashMap<String, String>
if (containersData.data.size > 0) {
val list = ArrayList<KeyValueModel>()
for (inside in data.keys) {
val ky = captionsMap[inside]
val value = data[inside].toString()
ky?.let { KeyValueModel(it, value) }?.let { list.add(it) }
}
DataListAdapter.updateInquiryAdapter(list)
} else {
errorMessage.value = activity.resources.getString(R.string.no_data)
}
if (containersData.ImageList != null && containersData.ImageList.isNotEmpty()) {
imagesAdapter.updateContainerImagesAdapter(containersData.ImageList)
}
}
private fun pickImages() {
activity.setCallBack(this)
val pictureDialog: AlertDialog
val builder = activity.let { AlertDialog.Builder(it) }
val dialogView = View.inflate(activity, R.layout.choose_camera_method, null)
builder.setView(dialogView)
val nafithPopupContainer = dialogView.findViewById<RelativeLayout>(R.id.RLTitle)
nafithPopupContainer.setBackgroundColor(
ContextCompat.getColor(
activity,
R.color.mainColor
)
)
val popUpGallery = dialogView.findViewById<LinearLayout>(R.id.PopupGellary)
val popUpCamera = dialogView.findViewById<LinearLayout>(R.id.PopupCamera)
pictureDialog = builder.create()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Objects.requireNonNull<Window>(pictureDialog.window)
.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
} else {
if (pictureDialog.window != null) {
pictureDialog.window!!.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
}
}
popUpGallery.setOnClickListener {
fromGallery()
pictureDialog.dismiss()
}
popUpCamera.setOnClickListener {
fromCamera()
pictureDialog.dismiss()
}
val popupClose = dialogView.findViewById<ImageView>(R.id.popupClose)
popupClose.setOnClickListener { pictureDialog.dismiss() }
pictureDialog.show()
}
private fun fromGallery() {
ImagePicker.create(activity)
.toolbarImageTitle(activity.resources.getString(R.string.get_image))
.toolbarArrowColor(ContextCompat.getColor(activity, R.color.colorWhite))
.showCamera(false)
.limit(6)
.start()
}
private fun fromCamera() {
ImagePicker.cameraOnly().start(activity)
}
override fun onGetImage(image: Image) {
imgeNoteVisibility.value = View.GONE
imagesAdapter.updateContainerImagesAdapter(image)
images.add(image)
}
override fun addingImagesDone(mImages: MutableList<Image>) {
images.clear()
images.addAll(mImages)
imgeNoteVisibility.value = View.GONE
val listString :ArrayList<String> = ArrayList()
for (i in mImages.indices){
listString.add(mImages[i].path)
}
imagesAdapters2.value = ContainerImagesAdapter2(activity,containersData.status!!,listString)
imagesAdapters2.value!!.notifyItemRangeChanged(0,listString.size)
}
override fun onImgDelete(image: String) {
var x = 0
try {
for (i in 0 until images.size) {
x = i
if (images[i].path == image) {
images.remove(images[i])
}
}
} catch (e: Exception) {
Log.e("errorImages", e.message!!)
Log.e("xx", x.toString())
}
}
private fun onRetrievePostListStart() {
loading.value = true
}
private fun onRetrievePostListFinish() {
loading.value = false
}
private fun onRetrievePostListSuccess(msg: String?) {
onRetrievePostListFinish()
}
private fun onRetrievePostListError(message: String?) {
onRetrievePostListFinish()
getDataError.value = true
errorMessage.value = message
}
}
Adapter code is :
class ContainerImagesAdapter2() : RecyclerView.Adapter<ContainerImagesAdapter2.ViewHolder>() {
var status: String = ""
lateinit var activity: LaunchActivity
lateinit var utility: Utility
constructor(
mActivity: LaunchActivity,
mStatus: String,
pathsList: ArrayList<String>
) : this() {
activity = mActivity
pathsDataSet = pathsList
status = mStatus
utility = Utility(activity)
}
private var pathsDataSet: ArrayList<String> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding: ContianerImageFieldBinding = DataBindingUtil
.inflate(
LayoutInflater.from(parent.context),
R.layout.contianer_image_field,
parent,
false
)
return ViewHolder(binding, activity)
}
override fun getItemCount(): Int {
return pathsDataSet.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindPath(pathsDataSet[position], position)
}
inner class ViewHolder(
private val binding: ContianerImageFieldBinding,
val activity: LaunchActivity
) : RecyclerView.ViewHolder(binding.root) {
private val viewModel = MscImagesListViewModel(activity)
fun bindPath(data: String, position: Int) {
viewModel.bindPath(data)
binding.viewModel = viewModel
if (status != "PENDING") {
binding.closeImg.visibility = View.GONE
}
binding.closeImg.setOnClickListener {}
binding.mainImg.setOnClickListener {
val fragment = FullImageFragment()
val bundle = Bundle()
val list = ArrayList<String>()
for (item in 0 until pathsDataSet.size) {
list.add(pathsDataSet[item])
}
bundle.putSerializable("ImageList", list)
bundle.putInt("Position", position)
fragment.arguments = bundle
activity.supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, fragment).addToBackStack(fragment.tag)
.commit()
}
}
}
}
if you filter data using search view in the first-page and pick images in the second page , list of picked images doesn't appear, if you going to the second page without filtering data everything ok
solve Problem found
Just Update constraint-layout library in gradle dependencies to version '2.0.0-beta4'
I have a list of user record sound
The user can click on the list and play the audio file
How can I handle the MediaPlayer and the RecyclerView item in the Seekbar as well in the MVVM correctly?
That is, when the user clicks, the visitor changes the item and updates itself, and when it is clicked on an item again, it updates itself.
I did it now, but unfortunately, to the dirtiest possible form
activity code :
class SoundListActivity : BaseActivity(), Observer<List<VoiceEntity>>, VoiceAdapter.OnClickItemListener,
OnMultiSelectVoiceListener {
private lateinit var viewModel: VoiceViewModel
private val adapter = VoiceAdapter()
private val player = MediaPlayer()
private var positionPlayItem = -1
companion object {
fun start(context: Context) {
context.startActivity(Intent(context, SoundListActivity::class.java))
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sound_list)
viewModel = ViewModelProviders.of(this).get(VoiceViewModel::class.java)
viewModel.mutableList!!.observe(this, this)
adapter.onItemClickListener = this
adapter.listenerMultiSelect = this
recycler.layoutManager = LinearLayoutManager(this)
recycler.adapter = adapter
fabAdd.setOnClickListener {
stopPlay()
RecordSoundActivity.start(this)
}
toolbar.setIconLeftListener(View.OnClickListener {
stopPlay()
finish()
})
}
override fun onChanged(list: List<VoiceEntity>?) {
this.progressBar.visibility = View.GONE
this.layoutEmptyState.visibility = View.INVISIBLE
this.adapter.removeAll()
if (list == null || list.isEmpty()) {
layoutEmptyState.visibility = View.VISIBLE
return
}
adapter.addItems(ArrayList(list))
}
override fun onClickItem(item: VoiceEntity, position: Int) {
if (player.isPlaying) {
player.reset()
}
if (item.isPlaying) {
item.isPlaying = false
player.reset()
adapter.notifyDataSetChanged()
return
}
this.positionPlayItem = position
adapter.items!!.forEach {
if (it != item) {
it.isPlaying = false
}
}
player.setDataSource(item.path)
player.prepare()
player.start()
item.isPlaying = true
adapter.notifyDataSetChanged()
player.setOnCompletionListener {
player.reset()
adapter.notifyItemChanged(position)
item.isPlaying = false
}
}
private fun stopPlay() {
if (positionPlayItem == -1) {
return
}
player.reset()
adapter.items!![positionPlayItem].isPlaying = false
adapter.notifyItemChanged(positionPlayItem)
}
override fun onMultiSelectVoice(items: ArrayList<VoiceEntity>) {
stopPlay()
if (items.size == 0) {
layoutSelectItem.visibility = View.GONE
return
}
txtCounterSelect.text = String.format(getString(R.string.selected_number), items.size.toString())
setStatusBarColor(R.color.black)
if (layoutSelectItem.visibility == View.GONE) {
layoutSelectItem.visibility = View.VISIBLE
}
if (items.size > 1) {
imgShare.visibility = View.GONE
imgEdit.visibility = View.GONE
} else {
imgShare.visibility = View.VISIBLE
imgEdit.visibility = View.VISIBLE
}
imgCancelSelect.setOnClickListener {
resetData()
}
imgEdit.setOnClickListener {
edit(items.first())
}
imgShare.setOnClickListener {
if (items.isEmpty()) {
return#setOnClickListener
}
shareVoice(this, items[0].path)
}
imgDelete.setOnClickListener {
val alertDialog = AlertDialog.Builder(
supportFragmentManager,
getString(R.string.note), getString(R.string.do_you_sure_delete)
)
alertDialog.setBtnNegative(getString(R.string.no), View.OnClickListener {
alertDialog.dialog!!.dismiss()
})
alertDialog.setBtnPositive(getString(R.string.yes), View.OnClickListener {
val ex = Executors.newSingleThreadExecutor()
items.forEach { item ->
viewModel.remove(item)
ex.execute { File(item.path).deleteOnExit() }
}
items.clear()
layoutSelectItem.visibility = View.GONE
setStatusBarColor(R.color.colorPrimaryDark)
alertDialog.dialog!!.dismissAllowingStateLoss()
})
alertDialog.build().show()
}
}
private fun resetData() {
adapter.itemsSelected.clear()
adapter.items?.forEach { item ->
item.statusSelect = false
}
adapter.notifyDataSetChanged()
layoutSelectItem.visibility = View.GONE
setStatusBarColor(R.color.colorPrimaryDark)
}
private fun edit(item: VoiceEntity) {
val bottomSheet = NameBottomSheet(supportFragmentManager)
bottomSheet.listener = object : NameBottomSheet.OnTitleListener {
override fun onTitle(title: String) {
item.title = title
viewModel.update(item)
resetData()
}
}
bottomSheet.item = item
bottomSheet.show()
}
override fun onBackPressed() {
if (layoutSelectItem.visibility == View.VISIBLE) {
resetData()
return
}
stopPlay()
super.onBackPressed()
}
}
adapter class code :
class VoiceAdapter : AdapterRecyclerView<VoiceEntity>() {
var onItemClickListener: OnClickItemListener? = null
var itemsSelected: ArrayList<VoiceEntity> = ArrayList()
var listenerMultiSelect: OnMultiSelectVoiceListener? = null
override fun getItemLayout(viewType: Int): Int {
return R.layout.item_voice
}
override fun onBindView(
viewDataBinding: ViewDataBinding,
viewHolder: ItemViewHolder,
position: Int,
viewType: Int,
element: VoiceEntity
) {
val binding = viewDataBinding as ItemVoiceBinding
binding.txtTitle.text = element.title
binding.txtDate.text = element.date.toAgoTime(context!!)
binding.icPlay.setImageResource(if (element.isPlaying) R.drawable.ic_pause else R.drawable.ic_play)
binding.seekBar.max = element.duration / 60
val colorSelectItem =
ContextCompat.getColor(binding.rootLayout.context, R.color.color_background_select_item_recycler_view)
val color = if (element.statusSelect) colorSelectItem else Color.TRANSPARENT
binding.rootLayout.setBackgroundColor(color)
if (element.statusSelect) {
changeColorLight(binding)
} else {
changeColorDarker(binding)
}
if (element.isPlaying) {
binding.layoutPlaying.visibility = View.VISIBLE
binding.lottieLayer.playAnimation()
//TODO : change handled voice progressBar show
val t = object : Thread() {
override fun run() {
super.run()
for (i in 0..element.duration) {
Thread.sleep(60)
binding.seekBar.progress = i
if (!element.isPlaying) break
}
}
}
t.start()
} else {
binding.layoutPlaying.visibility = View.GONE
binding.lottieLayer.cancelAnimation()
}
binding.rootLayout.setOnClickListener {
if (itemsSelected.size > 0) {
val item = items!![viewHolder.adapterPosition]
if (itemsSelected.contains(item)) {
item.statusSelect = false
itemsSelected.remove(item)
binding.rootLayout.animatedColorBackgroundSelected(false)
listenerMultiSelect?.onMultiSelectVoice(itemsSelected)
changeColorDarker(binding)
return#setOnClickListener
}
item.statusSelect = true
itemsSelected.add(item)
binding.rootLayout.animatedColorBackgroundSelected()
listenerMultiSelect?.onMultiSelectVoice(itemsSelected)
changeColorLight(binding)
return#setOnClickListener
}
onItemClickListener?.onClickItem(element, position)!!
}
binding.rootLayout.setOnLongClickListener {
val item = items!![viewHolder.adapterPosition]
if (itemsSelected.contains(item)) {
item.statusSelect = false
itemsSelected.remove(item)
binding.rootLayout.animatedColorBackgroundSelected(false)
changeColorDarker(binding)
listenerMultiSelect?.onMultiSelectVoice(itemsSelected)
}
item.statusSelect = true
itemsSelected.add(item)
binding.rootLayout.animatedColorBackgroundSelected()
changeColorLight(binding)
listenerMultiSelect?.onMultiSelectVoice(itemsSelected)
true
}
}
private fun changeColorLight(binding: ItemVoiceBinding) {
binding.txtDate.setTextColor(ContextCompat.getColor(binding.root.context, R.color.color_subtitle_light))
binding.txtTitle.setTextColor(ContextCompat.getColor(binding.root.context, R.color.color_title_light))
}
private fun changeColorDarker(binding: ItemVoiceBinding) {
binding.txtDate.setTextColor(ContextCompat.getColor(binding.root.context, R.color.color_subtitle))
binding.txtTitle.setTextColor(ContextCompat.getColor(binding.root.context, R.color.color_title))
}
interface OnClickItemListener {
fun onClickItem(item: VoiceEntity, position: Int)
}
}
github repository (open source project)
I have a android app, developed in kotlin.One of my activity have a tabview with viewpager to show the two tabs but here i have only one tabs is showed anther one does not display.when i open my activity only one tab is showed. what i make mistake please guide me.
private fun setupViewPager(viewPager: ViewPager, it: List<TransactionEntity>?, incoming: TransactionAdapterDirection) {
val adapter = ViewPagerAdapter(supportFragmentManager, viewPager, it, incoming, appDatabase, networkDefinitionProvider)
if(adapter.count < 2) {
if (incoming.equals(OUTGOING)) {
adapter.addFragment(SendingFragment(it!!, appDatabase, OUTGOING, networkDefinitionProvider), "SEND")
} else if (incoming.equals(INCOMING)) {
adapter.addFragment(ReceiveFragment(it!!, appDatabase, INCOMING, networkDefinitionProvider), "RECEIVE")
}
viewPager.setCurrentItem(0)
viewPager.adapter = adapter
}
}
my guess is, only one frament set in getItem() method
inner class ViewPagerAdapter(manager: FragmentManager, viewPager: ViewPager, it: List<TransactionEntity>?, incoming: TransactionAdapterDirection, appDatabase: AppDatabase, networkDefinitionProvider: NetworkDefinitionProvider) : FragmentStatePagerAdapter(manager) {
private val mFragmentList = ArrayList<Fragment>()
private val mFragmentTitleList = ArrayList<String>()
private val mfragmentAB = appDatabase
private val mfragmentIT: List<TransactionEntity> = it!!
private val mfragmentINC : TransactionAdapterDirection = incoming
private val mfragmentnetwork : NetworkDefinitionProvider = networkDefinitionProvider
/* override fun getItem(position: Int): Fragment {
return mFragmentList[position]
}*/
/*override fun getItem(position: Int): Fragment {
val fragment1 = ReceiveFragment(mfragmentIT,mfragmentAB,mfragmentINC,mfragmentnetwork)
return fragment1
}*/
override fun getItem(position: Int): Fragment? {
var fragment: Fragment? = null
if (position == 0) {
fragment = ReceiveFragment(mfragmentIT,mfragmentAB,mfragmentINC,mfragmentnetwork)
} else if (position == 1) {
fragment = SendingFragment(mfragmentIT,mfragmentAB,mfragmentINC,mfragmentnetwork)
}
return fragment
}
override fun getCount(): Int {
return mFragmentList.size
}
fun addFragment(fragment: Fragment, title: String) {
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
}
override fun getPageTitle(position: Int): CharSequence {
return mFragmentTitleList[position]
}
/*override fun getItemPosition(`object`: Any): Int {
return PagerAdapter.POSITION_NONE
}*/
override fun getItemPosition(fragItem: Any): Int {
var position = 0
if (fragItem is ReceiveFragment) {
position = 0
} else if (fragItem is SendingFragment) {
position = 1
}
return if (position >= 0) position else PagerAdapter.POSITION_NONE
}
}
MyFull Code:
class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceChangeListener, KodeinAware {
//tab
private var tabLayout: TabLayout? = null
var viewPager: ViewPager? = null
//private val tabIcons = intArrayOf(R.drawable.receive_tab, R.drawable.send_tab)
//end
/*private var tabLayout: TabLayout? = null
var viewPager: ViewPager? = null
private var viewPagerAdapter: ViewPagerAdapter? = null*/
//end
override val kodein by closestKodein()
val adapter = ViewPagerAdapter(supportFragmentManager)
private val actionBarDrawerToggle by lazy { ActionBarDrawerToggle(this, drawer_layout, R.string.drawer_open, R.string.drawer_close) }
private val syncProgressProvider: SyncProgressProvider by instance()
private val networkDefinitionProvider: NetworkDefinitionProvider by instance()
private val appDatabase: AppDatabase by instance()
private val settings: Settings by instance()
private val currentTokenProvider: CurrentTokenProvider by instance()
private val currentAddressProvider: CurrentAddressProvider by instance()
private var lastNightMode: Int? = null
private var balanceLiveData: LiveData<Balance>? = null
private var etherLiveData: LiveData<Balance>? = null
private val onboardingController by lazy { OnboardingController(this, settings) }
private var lastPastedData: String? = null
var t1: Int = 0
override fun onResume() {
super.onResume()
if (lastNightMode != null && lastNightMode != settings.getNightMode()) {
val intent = intent
finish()
startActivity(intent)
//recreateWhenPossible()
return
}
lastNightMode = settings.getNightMode()
setCurrentBalanceObservers()
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
if (clipboard.hasPrimaryClip()) {
val item = clipboard.primaryClip.getItemAt(0).text?.toString()
val erc681 = item?.let { EthereumURI(it).toERC681() }
if (erc681?.valid == true && erc681?.address != null && item != lastPastedData && item != currentAddressProvider.value?.hex.let { ERC681(address = it).generateURL() }) {
Snackbar.make(fab, R.string.paste_from_clipboard, Snackbar.LENGTH_INDEFINITE)
.addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
if (event == DISMISS_EVENT_ACTION || event == DISMISS_EVENT_SWIPE) {
lastPastedData = item
}
}
})
.setAction(R.string.paste_from_clipboard_action, {
alert(R.string.copied_string_warning_message, R.string.copied_string_warning_title) {
startActivity(Intent(this#MainActivity, CreateTransactionActivity::class.java).apply {
data = Uri.parse(item)
})
}
})
.show()
}
}
}
private fun String.isJSONKey() = try {
JSONObject(this).let {
it.has("address") && (it.has("crypto") || it.has("Crypto"))
}
} catch (e: Exception) {
false
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (data != null && data.hasExtra("SCAN_RESULT")) {
val scanResult = data.getStringExtra("SCAN_RESULT")
when {
scanResult.isEthereumURLString() -> {
startActivity(getEthereumViewIntent(scanResult))
}
scanResult.length == 64 -> {
startActivity(getKeyImportIntent(scanResult, KeyType.ECDSA))
}
scanResult.isJSONKey() -> {
startActivity(getKeyImportIntent(scanResult, KeyType.JSON))
}
/*scanResult.isUnsignedTransactionJSON() || scanResult.isSignedTransactionJSON() || scanResult.isParityUnsignedTransactionJSON() -> {
startActivity(getOfflineTransactionIntent(scanResult))
}*/
scanResult.startsWith("0x") -> {
startActivity(getEthereumViewIntent(ERC681(address = scanResult).generateURL()))
}
else -> {
AlertDialog.Builder(this)
.setMessage(R.string.scan_not_interpreted_error_message)
.setPositiveButton(android.R.string.ok, null)
.show()
}
}
}
}
fun refresh() {
val incomingSize = transaction_recycler_in.adapter?.itemCount ?: 0
val outgoingSize = transaction_recycler_out.adapter?.itemCount ?: 0
val hasTransactions = incomingSize + outgoingSize > 0
//empty_view_container.setVisibility(!hasTransactions && !onboardingController.isShowing)
transaction_recycler_out.setVisibility(hasTransactions)
transaction_recycler_in.setVisibility(hasTransactions)
//remove the textview based on the condition
if(hasTransactions.equals(true)){
empty_view.setVisibility(View.GONE)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
//val dateFormat = android.text.format.DateFormat.getDateFormat(applicationContext)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main_in_drawer_container)
onboardingController.install()
settings.registerListener(this)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
drawer_layout.addDrawerListener(actionBarDrawerToggle)
receive_button.setOnClickListener {
onboardingController.dismiss()
startActivityFromClass(RequestActivity::class)
}
send_button.setOnClickListener {
startActivityFromClass(CreateTransactionActivity::class)
}
fab.setOnClickListener {
startScanActivityForResult(this)
}
transaction_recycler_out.layoutManager = LinearLayoutManager(this)
transaction_recycler_in.layoutManager = LinearLayoutManager(this)
current_fiat_symbol.setOnClickListener {
startActivityFromClass(SelectReferenceActivity::class)
}
current_token_symbol.setOnClickListener {
startActivityFromClass(SelectTokenActivity::class)
}
syncProgressProvider.observe(this, Observer {
val progress = it!!
if (progress.isSyncing) {
val percent = ((progress.currentBlock.toDouble() / progress.highestBlock) * 100).toInt()
supportActionBar?.subtitle = "Block ${progress.currentBlock}/${progress.highestBlock} ($percent%)"
}
})
val incomingTransactionsObserver = Observer<List<TransactionEntity>> {
Log.e("INDIA", "incomingTransactionsObserver : " + it);
if (it != null) {
viewPager = findViewById(R.id.viewpager)
t1++
setupViewPager(viewPager!!, it, INCOMING)
tabLayout = findViewById(R.id.tabs);
tabLayout!!.setupWithViewPager(viewPager)
transaction_recycler_in.adapter = TransactionRecyclerAdapter(it, appDatabase, INCOMING, networkDefinitionProvider)
transaction_recycler_in.setVisibility(!it.isEmpty())
refresh()
}
}
val outgoingTransactionsObserver = Observer<List<TransactionEntity>> {
Log.e("INDIA", "outgoingTransactionsObserver : " + it);
if (it != null) {
viewPager = findViewById(R.id.viewpager)
t1++
setupViewPager(viewPager!!, it, OUTGOING)
tabLayout = findViewById(R.id.tabs);
tabLayout!!.setupWithViewPager(viewPager)
transaction_recycler_out.adapter = DuplicateTransactionRecyclerAdapter(it, appDatabase, OUTGOING, networkDefinitionProvider)
refresh()
}
}
var incomingTransactionsForAddress: LiveData<List<TransactionEntity>>? = null
var outgoingTransactionsForAddress: LiveData<List<TransactionEntity>>? = null
//fun installTransactionObservers() {
fun installTransactionObservers() {
incomingTransactionsForAddress?.removeObserver(incomingTransactionsObserver)
outgoingTransactionsForAddress?.removeObserver(outgoingTransactionsObserver)
currentAddressProvider.value?.let { currentAddress ->
val currentChain = networkDefinitionProvider.getCurrent().chain
incomingTransactionsForAddress = appDatabase.transactions.getIncomingTransactionsForAddressOnChainOrdered(currentAddress, currentChain)
outgoingTransactionsForAddress = appDatabase.transactions.getOutgoingTransactionsForAddressOnChainOrdered(currentAddress, currentChain)
incomingTransactionsForAddress?.observe(this, incomingTransactionsObserver)
outgoingTransactionsForAddress?.observe(this, outgoingTransactionsObserver)
}
}
networkDefinitionProvider.observe(this, Observer {
setCurrentBalanceObservers()
installTransactionObservers()
})
currentAddressProvider.observe(this, Observer {
installTransactionObservers()
})
currentAddressProvider.observe(this, Observer { _ ->
setCurrentBalanceObservers()
})
if (intent.action?.equals("org.walleth.action.SCAN") == true) {
startScanActivityForResult(this)
}
if (savedInstanceState != null) {
lastPastedData = savedInstanceState.getString(KEY_LAST_PASTED_DATA)
}
//progressBar.visibility = View.VISIBLE
}
private val balanceObserver = Observer<Balance> {
if (it != null) {
/* val progressBar: ProgressBar = this.progressBar1
progressBar.visibility = View.GONE*/
value_view.setValue(it.balance, currentTokenProvider.currentToken)
supportActionBar?.subtitle = getString(R.string.main_activity_block, it.block)
} else {
value_view.setValue(ZERO, currentTokenProvider.currentToken)
supportActionBar?.subtitle = getString(R.string.main_activity_no_data)
}
}
private val etherObserver = Observer<Balance> {
if (it != null) {
send_button.setVisibility(it.balance > ZERO, INVISIBLE)
} else {
send_button.visibility = INVISIBLE
}
}
private fun setCurrentBalanceObservers() {
Log.e("INDIA","currentAddress")
val currentAddress = currentAddressProvider.value
Log.e("INDIA","currentAddress" + currentAddress)
if (currentAddress != null) {
balanceLiveData?.removeObserver(balanceObserver)
balanceLiveData = appDatabase.balances.getBalanceLive(currentAddress, currentTokenProvider.currentToken.address, networkDefinitionProvider.getCurrent().chain)
balanceLiveData?.observe(this, balanceObserver)
etherLiveData?.removeObserver(etherObserver)
etherLiveData = appDatabase.balances.getBalanceLive(currentAddress, getEthTokenForChain(networkDefinitionProvider.getCurrent()).address, networkDefinitionProvider.getCurrent().chain)
etherLiveData?.observe(this, etherObserver)
}
}
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
actionBarDrawerToggle.syncState()
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
actionBarDrawerToggle.onConfigurationChanged(newConfig)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.menu_copy -> {
copyToClipboard(currentAddressProvider.getCurrent(), fab)
true
}
/*R.id.menu_info -> {
startActivityFromClass(InfoActivity::class.java)
true
}*/
else -> actionBarDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item)
}
override fun onSharedPreferenceChanged(preferences: SharedPreferences?, key: String?) {
if (Settings::currentFiat.name == key) {
transaction_recycler_in.adapter?.notifyDataSetChanged()
transaction_recycler_in.adapter?.notifyDataSetChanged()
}
}
override fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState)
outState!!.putString(KEY_LAST_PASTED_DATA, lastPastedData)
}
override fun onDestroy() {
settings.unregisterListener(this)
super.onDestroy()
}
//tab
private fun setupViewPager(viewPager: ViewPager, it: List<TransactionEntity>?, incoming: TransactionAdapterDirection) {
//val adapter = ViewPagerAdapter(supportFragmentManager, viewPager, it, incoming, appDatabase, networkDefinitionProvider)
if(adapter.count < 2) {
if (t1 == 1) {
adapter.addFragment(ReceiveFragment(it!!, appDatabase, INCOMING, networkDefinitionProvider), "SEND")
} else {
adapter.addFragment(SendingFragment(it!!, appDatabase, OUTGOING, networkDefinitionProvider), "RECEIVE")
}
if (t1 == 2) {
viewPager.adapter = adapter
}
}
}
//class ViewPagerAdapter(manager: FragmentManager, viewPager: ViewPager, it: List<TransactionEntity>?, incoming: TransactionAdapterDirection, appDatabase: AppDatabase, networkDefinitionProvider: NetworkDefinitionProvider) : FragmentStatePagerAdapter(manager) {
//class ViewPagerAdapter(manager: FragmentManager, viewPager: ViewPager, it: List<TransactionEntity>?, incoming: TransactionAdapterDirection, appDatabase: AppDatabase, networkDefinitionProvider: NetworkDefinitionProvider) : FragmentPagerAdapter(manager)
class ViewPagerAdapter(manager: FragmentManager) : FragmentStatePagerAdapter(manager)
{
private val mFragmentList: ArrayList<Fragment> = ArrayList<Fragment>()
private val mFragmentTitleList: ArrayList<String> = ArrayList<String>()
/*private val mfragmentAB = appDatabase
private val mfragmentIT: List<TransactionEntity> = it!!
private val mfragmentINC : TransactionAdapterDirection = incoming
private val mfragmentnetwork : NetworkDefinitionProvider = networkDefinitionProvider
private val mfragmentviewpager : ViewPager = viewPager*/
override fun getCount(): Int {
return mFragmentList.size
}
/* override fun getItem(position: Int): Fragment? {
var fragment: Fragment? = null
if (position == 0) {
fragment = SendingFragment(mfragmentIT, mfragmentAB, mfragmentINC, mfragmentnetwork)
} else if (position == 1) {
fragment = ReceiveFragment(mfragmentIT, mfragmentAB, mfragmentINC, mfragmentnetwork)
}
return fragment
}*/
override fun getItem(position: Int) = mFragmentList[position]
fun addFragment(fragment: Fragment, title: String) {
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
}
override fun getPageTitle(position: Int): CharSequence? {
return mFragmentTitleList[position]
}
override fun getItemPosition(fragItem: Any): Int {
var position = 0
if (fragItem is ReceiveFragment) {
position = 0
} else if (fragItem is SendingFragment) {
position = 1
}
return if (position >= 0) position else PagerAdapter.POSITION_NONE
}
}
}
Try something like:
class ViewPagerAdapter(manager: FragmentManager) : FragmentStatePagerAdapter(manager)
{
val incomingData: List<TransactionEntity> = mutableListOf()
val outgoingData: List<TransactionEntity> = mutableListOf()
override fun getCount(): Int = 2
override fun getItem(position: Int): Fragment {
return if (position == 0) SendingFragment(outgoingData, mfragmentAB, OUTGOING, mfragmentnetwork)
else ReceiveFragment(incomingData, mfragmentAB, INCOMING, mfragmentnetwork)
}
fun updateData(data: List<TransactionEntity>, isIncoming: Boolean) {
if (isIncoming) {
incomingData.clear()
incomingData.addAll(data)
} else {
outgoingData.clear()
outgoingData.addAll(data)
}
notifyDataSetChanged()
}
...
UPD
class MainActivity {
val incomingData: List<TransactionEntity> = mutableListOf()
val outgoingData: List<TransactionEntity> = mutableListOf()
...
private fun setupViewPager(viewPager: ViewPager, it: List<TransactionEntity>?, incoming: TransactionAdapterDirection) {
val adapter = ViewPagerAdapter(supportFragmentManager, viewPager, it, incoming, appDatabase, networkDefinitionProvider)
if(incoming == INCOMING) {
incomingData.clear()
incomingData.addAll(data)
} else {
outgoingData.clear()
outgoingData.addAll(data)
}
adapter.addFragment(ReceiveFragment(incomingData, appDatabase, INCOMING, networkDefinitionProvider), "SEND")
adapter.addFragment(SendingFragment(outgoingData, appDatabase, OUTGOING, networkDefinitionProvider), "RECEIVE")
viewPager.adapter = adapter
}
...
}