I want to create a horizontal progress bar in my splash screen activity
but when I write kotlin code to animate it, the id of the progressbar shows in red.
xml
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="150dp"
android:progressDrawable="#drawable/progress_bar"
android:layout_height="10dp"
android:layout_marginBottom="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
kt
class SplashScreen : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.splash_screen)
progressBar.max = 1000
val currentProg = 999
ObjectAnimator.ofInt(progressBar, "progress", currentProg)
.setDuration(4000)
.start()
}}
You should change your code like this
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.splash_screen)
findViewById<ProgressBar>(R.id.progressBar).apply {
max = 1000
val currentProg = 999
ObjectAnimator.ofInt(it, "progress", currentProg)
.setDuration(4000)
.start()
}
}}
Related
I'm trying to show BreakingNewsFragment through news activity using navigation
but the error is show
I am getting this error when trying to run this app. I have followed numerous guides to no avail. I am just trying to do the simplist exercise with navigation
Caused by: android.view.InflateException: Binary XML file line #20 in com.example.newsapp:layout/activity_news: Binary XML file line #20 in com.example.newsapp:layout/activity_news: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #20 in com.example.newsapp:layout/activity_news: Error inflating class fragment
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property newsViewModel has not been initialized
at com.example.newsapp.ui.activity.NewsActivity.getNewsViewModel(NewsActivity.kt:17)
at com.example.newsapp.ui.fragments.BreakingNewsFragment.onViewCreated(BreakingNewsFragment.kt:29)
newsActivity:
class NewsActivity : AppCompatActivity() {
lateinit var newsViewModel: NewsViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_news)
var newsRepository = NewsRepository(ArticleDataBase(this))
var newsViewModelFactoryProvider = NewsViewModelFactory(newsRepository)
newsViewModel = ViewModelProvider(this,newsViewModelFactoryProvider).get(NewsViewModel::class.java)
bottomNavigationView.setupWithNavController(navHostFragmentNews.findNavController())
}}
when to get newsViewModel from activity the error is show
in fragment:
class BreakingNewsFragment : Fragment(R.layout.fragment_breaking_news) {
lateinit var newsViewModel : NewsViewModel
lateinit var articleRecyclerAdapter: ArticleRecyclerAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
newsViewModel = (activity as NewsActivity).newsViewModel
setupRecyclerView()
}
fun setupRecyclerView(){
articleRecyclerAdapter= ArticleRecyclerAdapter()
rvBreakingNews.adapter= articleRecyclerAdapter
}}
xml code:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.NewsActivity">
<FrameLayout
android:id="#+id/flFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#+id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<fragment
android:name="androidx.navigation.fragment.NavHostFragment"
android:id="#+id/navHostFragmentNews"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph_news"/>
</FrameLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="56dp"
app:menu="#menu/menu_bottom_navigation_news"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
i use many fragment other it ,with them no any problem
why the error come in this fragment
you are initializing the newsViewModel after doing setContentView. So the fragment gets created before that. Try moving setContentView down, like this:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var newsRepository = NewsRepository(ArticleDataBase(this))
var newsViewModelFactoryProvider = NewsViewModelFactory(newsRepository)
newsViewModel = ViewModelProvider(this,newsViewModelFactoryProvider).get(NewsViewModel::class.java)
setContentView(R.layout.activity_news)
bottomNavigationView.setupWithNavController(navHostFragmentNews.findNavController())
}}
I know that this question has been answered 100 times but my code just doesn't work and I can't figure out what is wrong with it by reading posts made by others.
I want to make an app where when you open it u get a search filed, you tipe what u want to search and then click enter and you get what you searched for.
So, I'm trying to use DataBinding for that. In the activity xml file i wrapped everything with the layout tag :
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<fragment
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/TitleFragment"
/>
</layout
And here is my MainActivty:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
#Suppress("UNUSED_VARIABLE")
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
}
}
and my TitleFragment:
class TitleFragment : Fragment() {
//Inflating and Returning the View with DataBindingUtil
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_title, container, false)
}
}
I just want to be able to open the app with the fragment_title.xml showing via the activity_main as i want to use databinding for opening my views.
I keep getting the error "Unresolved reference: ActivityMainBinding" but in the build.gradle i included
databinding=true
viewbinding=true
but nothing works.
How do i fix this error and did i even return the fragment correctly?
TitleFragment
private var _binding: FragmentTitleBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
//...this is code ...
return binding.root
}
MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDoctorHomeBinding.inflate(layoutInflater)
}
I want to validate form login Kotlin with Application Structure Model–view–viewmodel
I used ViewModel with Data Binding and LiveData, Create a variable in the XML file for Two-Way Data
I can validate when empty field but I don't know How to set error for editText when user change EditText invited format or worng characters
activity_main.xml
<data><variable
name="viewModel"
type="com.validateform.LoginViewModel" />
</data>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/lay_username"
android:layout_width="350dp"
android:layout_height="wrap_content"
android:hint="Username"
app:errorEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/edt_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#={viewModel.username}" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/lay_password"
android:layout_width="350dp"
android:layout_height="wrap_content"
android:hint="Password"
app:errorEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/edt_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#={viewModel.password}" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="#+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="#{()-> viewModel.submitLogin()}"
android:text="Submit"/>
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel : LoginViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Binding
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
// ViewModel
viewModel = ViewModelProviders.of(this).get(LoginViewModel::class.java)
binding.lifecycleOwner = this
binding.viewModel = viewModel
initObserver()
}
private fun initObserver() {
viewModel.errorMessage.observe(this, Observer { message ->
Snackbar.make(binding.btnSubmit, message, Snackbar.LENGTH_LONG).show()
})
}
}
LoginViewModel.kt
class LoginViewModel : ViewModel() {
val username = MutableLiveData()
val password = MutableLiveData()
private val _errorMessage = MutableLiveData()
val errorMessage : LiveData
get() = _errorMessage
fun submitLogin() {
validateForm()
}
private fun validateForm() : Boolean {
var result = true
if (username.value.isNullOrEmpty()) {
_errorMessage.value = "User Required"
result = false
}
if (password.value.isNullOrEmpty()) {
_errorMessage.value = "Password Required"
result = false
}
return result
}
}
You need to return error message as a string resource to support localization. Also, you need to create binding adapter for it.
View model sample
interface LoginViewModel {
val errorMessage: LiveData<Int>
}
Binding adapter sample
#BindingAdapter("error")
internal fun TextInputLayout.setError(#StringRes errorRes: Int) {
error = errorRes.takeUnless { it == ID_NULL }?.let { resources.getString(it) }
}
Layout
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/lay_username"
android:layout_width="350dp"
android:layout_height="wrap_content"
android:hint="Username"
app:errorEnabled="true"
bind:error="#{ vm.errorMessage }">
</com.google.android.material.textfield.TextInputLayout>
Note: you don't need flag app:errorEnabled="true" if your provide helper text. It main purpose to reserve space for the message.
I am working on an app where click on an item in a recycler View opens another activity (Customer-Detail) where there are three Fragments in Tab layout .recycler view contains list of employees, I want to show the details of employee selected from list. I have stored All employee's data in SQLITE in "Employee" Table ( which contains Customer-Id ,Name ,Address ETC) , Now I have Customer-ID (ID of selected Customer) in "Customer-Detail" Activity. I just want to send that "Customer-ID" value to three Fragments of this Customer-Detail Activity. It seems simple but I could not find any solution . Here is my CustomerDetail.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CustomerDetail">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/custID"
/>
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabInlineLabel="true"
app:tabBackground="#color/lightRed"
app:tabIndicatorColor="#color/white"
app:tabTextColor="#color/white"
app:tabMode="fixed"
android:id="#+id/tablayout"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/appbar"
android:id="#+id/viewPager"
/>
</RelativeLayout>
Here is CustomerDetails.kt :
class CustomerDetail : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_customer_detail)
val extras: Bundle? = intent.extras
val EmployeeID: Int = extras!!.getInt("id")
sendToFragmentOrder(EmployeeID)
val appbar = findViewById<AppBarLayout>(R.id.appbar)
val tabLayout = findViewById<TabLayout>(R.id.tablayout)
val viewPager = findViewById<ViewPager>(R.id.viewPager)
setUpTabs()
}
private fun sendToFragmentOrder(id : Int) {
// this method is not working...
val bundle = Bundle()
bundle.putInt("id",id)
val fragmentOrder = OrderFragment()
fragmentOrder.arguments = bundle
}
private fun setUpTabs() {
val adapter = mPagerAdapter(supportFragmentManager)
adapter.addFragment(OrderFragment(), "Orders")
adapter.addFragment(ReceiptsFragment(), "Receipts")
adapter.addFragment(ReportsFragment(), "Reports")
val viewpager = findViewById<ViewPager>(R.id.viewPager)
viewpager.adapter = adapter
val tab = findViewById<TabLayout>(R.id.tablayout)
tab.setupWithViewPager(viewpager)
}
}
OrderFragment() Class :
class OrderFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val id = arguments?.getInt("id")
val view=inflater.inflate(R.layout.fragment_order, container, false)
val tv = view.findViewById<TextView>(R.id.idtv)
tv.text = id.toString()
return view }
}
i hope i explained my question well ... i am new here so ... any help will be appreciated
use the same viewmodel:
in Activity:
val viewModel: MyViewModel by viewModels()
in Fragment:
val viewModel: MyViewModel by activityViewModels()
needs ktx artifcats, see https://developer.android.com/topic/libraries/architecture/viewmodel
this is the XML which seems okay
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/iam_a_rider"
android:id= "#+id/rider"/>
//this the XML code for the button I created that I would like to declare in the main activity page
this is the code I was trying to execute but was not successful since it keeps bring an error of val not recognised with in the code
main activity kt
class MainActivity : AppCompatActivity()
{
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rider: Button = findViewById<Button>(R.id.rider)
rider.setOnClickListener()
// still brings an error of rider not in use or doesn't recognise it at all
}