Rotating screen does not save text colour kotlin - android-studio

I have a simple increment app. When you press on the button the number goes up. However i also made the number change to red once it's higher then 5.
I was able to get the number to save on rotation however the colour resets back to normal.
I'm not sure how i can also save the colour. Any ideas on how i can do this?
// number starts at 0
var num = 0
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView = findViewById<TextView>(R.id.textView)
val add = findViewById<Button>(R.id.button)
add.setOnClickListener {
++num
if(num > 5) {
textView.setTextColor(Color.parseColor("#FF0000"))
}
textView.setText(num.toString())
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putInt("int", num)
}
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
if(savedInstanceState != null) {
num = savedInstanceState.getInt("int")
textView.setText(num.toString())
}
}
}

update this method onRestoreInstanceState
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
if(savedInstanceState != null) {
num = savedInstanceState.getInt("int")
if(num > 5){
textView.setTextColor(Color.parseColor("#FF0000"))
}
textView.setText(num.toString())
}
}

Related

how to handle imepadding when textfield is at bottom of view in jetpack compose?

When the basictextfield is at bottom of view and is focused, the basictextfield is moving to the center of screen. How can I stop that? If I remove imePadding(), only half of textfield is visible.
#AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
var a by remember {
mutableStateOf("")
}
Box(
modifier = Modifier
.fillMaxSize()
.imePadding()
) {
BasicTextField(
value = a, onValueChange = { a = it }, modifier = Modifier.align(
Alignment.BottomCenter
)
)
}
}
}
}

Why does navigation composable call twice?

Why does navigation composable call twice? If I set a breakpoint on the Text I will get two stops when the app runs. Thank you for your answers.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
var i: Int = 0
NavHost(navController = navController, startDestination = "s1") {
composable("s1") {
i++
Text("$i")
}
}
}
}
}

Clearing a RecyclerView when User makes a second request (using diffUtils and livedata)

I have made an app that uses an API to make a request and then shows the results in a RecyclerView.
I was following a tutorial and in it they used a differCallback and a liveData so the lists updates and such. However whenever the user makes a second search, the recyclerView should only show the new results but the previous results don't dissapear and the new results just appear below the previous search.
I have debugged it for quite some time now but I don't seem to understand where the list is made and where sure it be updated (or in this case cleared).
I tried using .clear() for the diff (Asynclistdiffer), creating a new list in the onBindViewHolder and then clearing that list every time the "search" is called but without any luck. As im still a beginner I don't have a clue on where or what is happening, all your helo will be greatly appreciated
this is my adapter:
class RecipePreviewAdapter : RecyclerView.Adapter<RecipePreviewAdapter.RecipePreviewViewHolder>() {
inner class RecipePreviewViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
private val differCallback = object : DiffUtil.ItemCallback<Recipe>() {
override fun areItemsTheSame(oldItem: Recipe, newItem: Recipe): Boolean {
return oldItem.sourceUrl == newItem.sourceUrl
}
override fun areContentsTheSame(oldItem: Recipe, newItem: Recipe): Boolean {
return oldItem == newItem
}
}
val differ = AsyncListDiffer(this, differCallback)
lateinit var recipeList: MutableList<Recipe>
var isRecipeListInitialized = false
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecipePreviewViewHolder {
return RecipePreviewViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_recipe_preview,
parent,
false
)
)
}
override fun onBindViewHolder(holder: RecipePreviewViewHolder, position: Int) {
recipeList = differ.currentList.toMutableList()
isRecipeListInitialized = true
// Log.d(TAG, recipeList.toString())
val recipe = recipeList[position]
holder.itemView.apply {
Glide.with(this).load(recipe.image).into(ivRecipeImagePreview)
tvRecipeTitlePreview.text = recipe.title
tvTimeToMakeTVPreview.text = "${recipe.readyInMinutes} minutes"
tvSummaryPreview.text = Jsoup.parse(recipe.summary).text()
setOnClickListener {
onItemClickListener?.let { it(recipe) }
}
}
}
override fun getItemCount(): Int {
return differ.currentList.size
}
And this is where I call it:
class SearchRecipeFragment : Fragment(R.layout.fragment_search_recipe) {
lateinit var viewModel: RecipeViewModel
lateinit var recipeAdapter: RecipePreviewAdapter
val TAG = "SearchRecipeFragment"
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = (activity as RecipesActivity).viewModel
setupRecyclerView()
recipeAdapter.setOnItemClickListener {
val bundle = Bundle().apply {
putSerializable("recipe", it)
}
findNavController().navigate(
R.id.action_searchRecipeFragment_to_recipeFragment,
bundle
)
}
etSearch.setOnKeyListener(View.OnKeyListener { _, keyCode, event ->
if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_DOWN) {
if (etSearch.text.toString().isNotEmpty()) {
viewModel.searchRecipe(etSearch.text.toString())
}
return#OnKeyListener true
}
false
})
viewModel.searchRecipeLiveData.observe(viewLifecycleOwner, Observer { response ->
when (response) {
is Resource.Success -> {
hideProgressBar()
response.data?.let { recipeResponse ->
recipeAdapter.differ.submitList(recipeResponse.results.toList())
}
}
is Resource.Error -> {
hideProgressBar()
response.message?.let { message ->
Log.e(TAG, "An error occurred: $message")
Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG)
.show()
}
}
is Resource.Loading -> {
showProgressBar()
}
}
})
}
Ans this is the part of the ViewModel that I'm not really sure what it does
private fun handleSearchRecipeResponse(response: Response<SearchRecipeResponse>): Resource<SearchRecipeResponse> {
if (response.isSuccessful) {
response.body()?.let { resultResponse ->
searchRecipesPage++
if (searchRecipesResponse == null) {
searchRecipesResponse = resultResponse
} else {
val oldRecipes = searchRecipesResponse?.results
val newRecipes = resultResponse.results
oldRecipes?.addAll(newRecipes)
}
return Resource.Success(searchRecipesResponse ?: resultResponse)
}
}
return Resource.Error(response.message())
}
too late but it is because of "searchRecipesResponse". You have to set it to "null" and reset searchRecipesPage to 1 for each new search in etSearch.setOnKeyListener().

How to change the value of the adapter position in the activity in an OnClick?

In my adapter of a ViewPager I have the position. What I want to do is add 1 to the position by pressing a Button in the activity but I cannot access the position from the activity. How can I do it?
Adapter:
class MyAdapter(var context: Context,private var myList: List<MyModel>) : PagerAdapter() {
override fun getCount(): Int {
return myList.size
}
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view == `object`
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
container.removeView(`object` as View?)
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
var view: View = LayoutInflater.from(context).inflate(R.layout.layout_item,container,false)
var img: ImageView = view.findViewById(R.id.imgView)
val listPos= myList[position]
container.addView(view)
return view
}
}
Activity:
class MyActivity : AppCompatActivity() {
private var myAdapter: MyAdapter? = null
private val myList = ArrayList<MyModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.my_activity_layout)
myAdapter = MyAdapter(this,myList)
myViewPager.adapter = myAdapter
myList.add("Name",R.drawable.img1)
myList.add("Name2",R.drawable.img2)
myList.add("Name3",R.drawable.img3)
myButtonPlus.setOnClickListener{
//Here I want to +1 the position for every click
}
myButtonMinus.setOnClickListener{
//Here I want to -1 the position for every click
}
}
}
If you want to increase and decrease your ViewPager position you should use the setCurrentItem function.
Try to change your code like this:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.my_activity_layout)
myAdapter = MyAdapter(this,myList)
myViewPager.adapter = myAdapter
myList.add("Name",R.drawable.img1)
myList.add("Name2",R.drawable.img2)
myList.add("Name3",R.drawable.img3)
myButtonPlus.setOnClickListener{
//Here I want to +1 the position for every click
val currentPage = myAdapter?.currentItem ?: 0
val maxPage = myAdapter?.childCount ?: 0
if (currentPage < maxPage) {
myAdapter?.currentItem = currentPage + 1
}
}
myButtonMinus.setOnClickListener{
//Here I want to -1 the position for every click
val currentPage = myAdapter?.currentItem ?: 0
if (currentPage > 0) {
myAdapter?.currentItem = currentPage - 1
}
}
}

How To Show Interstitial Ads in The getView Function in Kotlin?

I'm a Beginner in Kotlin and I want a way to display Interstitial Ad every time I click on the button tvName, but on the contrary, the app crashes whenever I click on the button. I searched for the solution for a long time.
Here's MainActivity
import ...
#Suppress("UNREACHABLE_CODE")
class MainActivity : AppCompatActivity() {
lateinit var mAdView : AdView
var adapter:ChaptersAdapter?=null
var listOfChapters= ArrayList<Chapters>()
#SuppressLint("WrongViewCast")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
MobileAds.initialize(this) {}
mAdView = findViewById(R.id.adView)
val adRequest = AdRequest.Builder().build()
mAdView.loadAd(adRequest)
loadChapters()
adapter = ChaptersAdapter(listOfChapters, this)
lvchapters.adapter = adapter
MobileAds.initialize(this,
"ca-app-pub-3940256099942544~3347511713")
mInterstitialAd = InterstitialAd(this)
mInterstitialAd.adUnitId = "ca-app-pub-3940256099942544/1033173712"
mInterstitialAd.loadAd(AdRequest.Builder().build())
}
fun loadChapters(){
listOfChapters.add(Chapters(" Chapter 1 ", applicationContext.assets.open("Chapter0.txt").bufferedReader().use {
it.readText()
}
))
listOfChapters.add(Chapters(" Chapter 2 ", applicationContext.assets.open("Chapter1.txt").bufferedReader().use {
it.readText()
}
))
}
class ChaptersAdapter: BaseAdapter {
var context:Context?=null
var listOfChaptersLocal= ArrayList<Chapters>()
constructor(listOfChapters:ArrayList<Chapters>,context:Context){
listOfChaptersLocal=listOfChapters
this.context=context
}
override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View {
val chapters= listOfChaptersLocal[p0]
var inflator= context!!.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val chaptersView=inflator.inflate(R.layout.list_chapters,null)
chaptersView.tvName.text= chapters.name!!
chaptersView.**tvName.setOnClickListener** {
// **i want to show the Ads in this time frame** but like this example it didn't work
if (mInterstitialAd.isLoaded) {
mInterstitialAd.show()
} else {
Log.d("TAG", "The interstitial wasn't loaded yet.")
}
val intent =Intent(context,ChapterDetails::class.java)
intent.putExtra("name",chapters.name!!)
intent.putExtra("des",chapters.des!!)
context!!.startActivity(intent)
}
return chaptersView
}
override fun getItem(p0: Int): Any {
return listOfChaptersLocal[p0]
}
override fun getItemId(p0: Int): Long {
return p0.toLong()
}
override fun getCount(): Int {
return listOfChaptersLocal.size
}
}
}

Resources