How to add a common button in all activity? - android

Can we add a common button on all activity without add code in xml file.
we need to add some code in application class and button show in all activity of app.

First create a BaseActivity. Then add this code to onCreate of that:
class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_nav_host)
//the layout of baseActivity
LinearLayout layout =(LinearLayout) findViewById (R.id.base_activity_layout);
//set the properties for button
Button btnTag = new Button(this);
btnTag.setLayoutParams(
new LayoutParams (LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT
));
btnTag.setText("Button");
btnTag.setId(some_random_id);
//add button to the layout
layout.addView(btnTag);
}
}
Then let other activities which you want to create being inherited from BaseActivity.
class FirstActivity : BaseActivity() {
//
//
}
class SecondActivity : BaseActivity() {
//
//
}
class ThirdActivity : BaseActivity() {
//
//
}

class ButtonActivity: Activity() {
protected var btnCommon: Button
override fun onCreate(saved: Bundle?) {
var layout = findViewById(R.id.layout) as ConstraintLayout
btnCommon = Button(this)
// set Button properties
layout.addView(button)
}
}
How to use
class MyActivity: ButtonActivity() {
onCreate() {
this.btnCommon.setOnClickListener...... // now you can use.
}
}

I saw in your comments that you specifically want to do this solely from your Application class. It is possible to add a callback that is called during lifecycle methods of every Activity, so you could add a button there. Every one of your Activities will have to have a root view in its layout of the same type and with the same ID for this to work.
class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
registerActivityLifecycleCallbacks(object: ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
val rootView = activity.findViewById<ConstraintLayout>(R.id.myRootView)
val layoutParams = ConstraintLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
).apply {
// Set up the appropriate layout constraints here
}
val button = Button(/* ... */)
rootView.addView(button, layoutParams)
}
override fun onActivityStarted(activity: Activity) = Unit
override fun onActivityResumed(activity: Activity) = Unit
override fun onActivityPaused(activity: Activity) = Unit
override fun onActivityStopped(activity: Activity) = Unit
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) = Unit
override fun onActivityDestroyed(activity: Activity) = Unit
})
}
}
Personally, I think this is messy, and I would do it in a top level function that you call from onCreate() in each of your Activities. Or better yet, use a single Activity in your app and use Fragments for the different screens.

Related

How to start another activity in function? Kotlin

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navigate = Intent(this,Activity2::class.java)
startActivity(navigate)
}
}
}
fun switchActivity(){
val navigate = Intent(this,Activity2::class.java)
startActivity(navigate)
}
I want to start an activity from a function and not from the main activity..
I can start an activity from main class but in function, the code doesnt work..
Please help.. I'm new to kotlin android programming..
You can also try like this
class MainActivity : AppCompatActivity() {
#SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
nextActivity(this, MainActivity2())
}
private fun nextActivity(context: Context, activity: Activity) {
startActivity(Intent(context, activity::class.java))
}
}
Just use it
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
switchActivity()
}
}
fun switchActivity(){
val navigate = Intent(this#MainActivity, Activity2::class.java)
startActivity(navigate)
}
Actually i don't get your question clearly. But i'll try to answer your question based on my understanding of yours.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
switchActivity()
// if you want to pass the class through the paramater,
// can try this
// TODO: Another Way
// switchActivityCustom(Activity2::class.java)
}
}
fun switchActivity(){
val navigate = Intent(this, Activity2::class.java)
startActivity(navigate)
}
// TODO: Another Function
// fun switchActivityCustom(destination: Class<*>,){
// val navigate = Intent(this, destination)
// startActivity(navigate)
// }
}
And the last one is, put your function inside the class (in this case: MainActivity Class)
If your function is declared at the top level, without a reference to this, you'd need to pass an instance of Activity to your function:
fun switchActivity(activity: Activity) {
val navigate = Intent(activity, Activity2::class.java)
activity.startActivity(navigate)
}

How to call composable Alertdialog from non composable function

I wanted to check whether the phone is rooted or not. For that I wanted to check as soon as the app is clicked.
#HiltAndroidApp class ShoppingApp : Application(), Configuration.Provider {
override fun onCreate() {
super.onCreate() }
This is the first class which is called as soon as the app is launched. Inside this onCreate, I wanted to add check if device is rooted. If its rooted I want to show AlertDialog else navigate to next screen.
When adding composable AlertDialog, its throwing error #Composable should be called from the context of Composable.
In this case, how should I code.
You will need to create a State object in your Application class and make your composable observe that object from an Activity or Fragment.
class ShoppingApp : Application() {
val isRootedState = mutableStateOf(false)
override fun onCreate() {
super.onCreate()
if (isRootedDevice()) {
isRootedState.value = true
}
}
}
class ShoppingActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val isRooted = remember { (application as ShoppingApp).isRootedState }
if (isRooted.value) {
AlertDialog(
// AlertDialog params
)
}
}
}
//...
}

When to call livedata observer?

On a button click i have to get some value from API call and then launch one screen. I have two options:
Call the observer each time when user will click on button.
Call the observer on fragment onActivityCreated() and store the value in variable and act accordingly on button click.
So which approach I should follow?
Actually it's up to you. But i always prefer to call it in Activity's onCreate() function, so activity only has 1 observer. If you call it in button click, it will give you multiple observers as much as button clicking
Here is some example :
class HomeProfileActivity: BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initObserver()
initView()
}
private fun initObserver() {
viewModel.profileWorkProccess.observe(this, {
swipeRefreshLayout.isRefreshing = it
})
viewModel.isLoadingJobs.observe(this, {
layoutProgressBarJobs.visibility = View.VISIBLE
recyclerViewJobs.visibility = View.GONE
dotsJobs.visibility = View.GONE
})
//other viewmodel observing ......
}
private fun initView() {
imageProfile.loadUrl(user.image, R.drawable.ic_user)
textName.text = identity.user?.fullName
textAddress.text = identity.user?.city
buttonGetData.setOnClickListener { viewModel.getData(this) }
}
}
If the button is placed on the Activity, and data is displayed in the Fragment, you need to store variable in Activity ViewModel and observe it in Fragment
You only need to call observe one time when fragment is created.
For example:
class MyActivity : AppCompatActivity() {
val viewModel: MyActViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
myButton.setOnClickListener { view ->
viewModel.getData()
}
}
}
class MyActViewModel: ViewModel {
val data: LiveData<String> = MutableLiveData()
fun getData() {}
}
class MyFragment: Fragment {
val actViewModel: MyActViewModel by activityViewModels()
override fun onActivityCreated(...) {
....
actViewModel.data.observe(viewLifecycleOwner, Observer { data ->
...
}
}
}

Object is not abstract and does not implement abstract member public abstract fun onClick(p0: View!): Unit

I haven't found anything over the past day that shows how to do this action, everything I've seen is with a basic button of which I am unable to replicate for use with an image button. using setOnClickListener does not seem to work at all though the only cases I found of using them were 5+ years old.
Is there a Storyboard equivalent of linking activities in Android Studio?
Here is an example I found but 7 years old.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myButton =
findViewById<View>(R.id.live) as ImageButton
myButton.setOnClickListener(object : OnClickListener() {
// When the button is pressed/clicked, it will run the code below
fun onClick() {
// Intent is what you use to start another activity
val intent = Intent(this, LiveActivity::class.java)
startActivity(intent)
}
})
}
}
gives the following error:
Object is not abstract and does not implement abstract member public abstract fun onClick(p0: View!): Unit defined in android.view.View.OnClickListener
The problem is that you haven't included the View parameter to your onClick override. The signature of OnClickListener.onClick includes a View (the View that was clicked) as its parameter, so onClick() (with no parameters) doesn't match that signature.
You could either add it explicitly (in which case you also need to refer to the Activity's this explicitly with ActivityName.this, as this refers to the OnClickListener otherwise):
myButton.setOnClickListener(object : View.OnClickListener {
// When the button is pressed/clicked, it will run the code below
override fun onClick(view: View) {
// Replace ActivityName with the name of your Activity that this is in
val intent = Intent(ActivityName.this, LiveActivity::class.java)
startActivity(intent)
}
})
or use Kotlin's SAM conversions to add it implicitly (I'd do this approach):
// When the button is pressed/clicked, it will run the code below
myButton.setOnClickListener { // there's an implicit view parameter as "it"
// Intent is what you use to start another activity
val intent = Intent(this, LiveActivity::class.java)
startActivity(intent)
}
Fix
Change from:
myButton.setOnClickListener(object : OnClickListener { })
to
myButton.setOnClickListener(object : View.OnClickListener { })
so method will be:
override fun onClick(v: View?) {
// Do something
}
instead yours:
fun onClick() {
}
Full code:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myButton = findViewById<ImageButton>(R.id.live)
myButton.setOnClickListener(object : View.OnClickListener {
// When the button is pressed/clicked, it will run the code below
override fun onClick(v: View?) {
// Intent is what you use to start another activity
val intent = Intent(this, LiveActivity::class.java)
startActivity(intent)
}
})
}
}

How to use interface in Android

I know the concept of "Interfaces" but I've hard time to understand how to use them in android development.
Let's say I created an interface to decide if to show progress bar or not -
interface ProgressBarInterface {
fun showProgressBar()
fun hideProgressBar()
}
And I implement this inside BaseActivity/MainActivity in single Activity app:
class BaseActivity : AppCompatActivity() , ProgressBarInterface {
private val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun showProgressBar() {
}
override fun hideProgressBar() {
}
}
And inside my other activity I've a button, that when I click on it, I want to trigger showProgressBar in the base activity:
button.setOnClickListener {
//Show progress bar
}
How can I interact with the interface to trigger the function inside base activity?
Since you already are implementing the interface in your BaseActivity, you can then just add what you need to do inside the interface methods, and then call them up in any point in your activity, if what you are looking for is to extend this BaseActiviy into more activities you will need to make this BaseActivity abstract then you can extend in each activity this BaseClass and just use the interface methods
abstract class BaseActivity : AppCompatActivity() , ProgressBarInterface {
private val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun showProgressBar() {
progressBar.visibility = View.VISIBLE
}
override fun hideProgressBar() {
progressBar.visibility = View.GONE
}
}
and then in your Activities you can extend from BaseActivity() and just use your interface methods as you have defined in that BaseActivity() to prevent coding them again, you can do
class FirstActivity : BaseActivity() {
...
button.setOnClickListener {
showProgressBar()
}
An easier way to show and hide the views? Use extension functions
fun View.show() {
this.visibility = View.VISIBLE
}
fun View.hide() {
this.visibility = View.GONE
}
you can define that extensions in any class, for example ViewUtils.kt and then just call
button.setOnClickListener {
progressBar.show()
}
or
button.setOnClickListener {
progressBar.hide()
}

Categories

Resources