Pass data by pressing tab in android - java

I wonder how to pass data by pressing tab. I have two tab in activity, named Info and Details. When Details tab is clicked, I want to pass the title editText to next activity.
P/S : Without button clicked
MainActivity
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabReselected(p0: TabLayout.Tab?) {
}
override fun onTabSelected(p0: TabLayout.Tab?) {
val position = p0?.position
when (position) {
0 ->
supportFragmentManager.beginTransaction().replace(
R.id.frame_container,
CreateWOInfoFragment()
).addToBackStack(null).commit()
else -> supportFragmentManager.beginTransaction().replace(
R.id.frame_container,
CreateWODetailsFragment()
).addToBackStack(null).commit()
}
}
override fun onTabUnselected(p0: TabLayout.Tab?) {
}
})

FragmentOne would be sending the data entered in EditText to FragmentTwo.
So add an interface in fragment one and let the activity implement this interface,
in Fragment one call the method to send data and in main fragment will handle it to send it to fragment two.
Please check this example Android Passing Data between Fragments

Related

Is it possible to invoke a back button click programmatically?

I've seen plenty of answers explaining how to override and add functionality to a back button press via user's interaction, but almost none of the answers explain how to programmatically trigger a back button press without any user input. Answers that do address it give somewhat deprecated code samples that don't really compute.
From your activity just call => onBackPressed(),
or form your fragment => activity?.onBackPressed()
//simply put this code where you want to make back intent
super.onBackPressed();
According to official docs onBackPressed is deprecated in Api level 33.
you can now use onBackPressedDispatcher please follow these steps:
Add android:enableOnBackInvokedCallBack="true” inside application tag
in manifest folder.
Kotlin code :
class YourActivity : AppCompatActivity() {
lateinit var button: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button = findViewById(R.id.txt)
button.setOnClickListener {
onBackPressedCallback.handleOnBackPressed()
}
}
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
finish() //this finishes the current activity
// Your business logic to handle the back pressed event
}
}
}
And here is old way of implementation:
Java :
buttonBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
YourActivity.super.onBackPressed();
}
});
Kotlin :
buttonBack.setOnClickListener{
super.onBackPressed()
}

get result from activity in adapter

In my fragment I have a recycler view and set adapter to it. With adapter's help I can start start second activity by clicking on items in recycler view. But when I finish second activity I need to call one method again in my fragment.
I can start activityForResult only in adapter, but I write onActivityResult method in it.
How can I get result from the activity or call method in fragment again? Is it possible to get result from activity in adapter?
In general, the Adapter should only care about creating RecyclerView cells. Any other logic is better put elsewhere (Activity/Fragment, or better - ViewModel/Presenter)
In case you don't have a view model per RecyclerView cell, I would use an interface to let the Fragment know that an item was clicked:
public interface ItemClickedListener {
fun itemClicked(String itemName)
}
In your Adapter:
public class YourAdapter(private val listener: ItemClickedListener): RecyclerView.Adapter<ViewHolder> {
}
In your Fragment (where you create your Adapter) pass "this" as the ItemClickedListener:
adapter = YourAdapter(this)
Have your Fragment implement ItemClickedListener & onActivityResult:
public class YourFragment: Fragment, ItemClickedListener {
override fun itemClicked(String itemName) {
startActivityForResult(...)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Let your adapter know whatever is needed
}
}
Back in your Adapter, instead of calling startActivityForResult upon item click - call listener.itemClicked
This is a basic example of removing the navigation logic from the Adapter.
Now the Fragment is making decisions about navigation, which might be OK if no business logic is involved.
For cases where more business logic is needed, a better paradigm should be used (MVP, MVVM, MVI, etc..).
As Android recommends using MVVM, I would advice you to read this:
https://developer.android.com/topic/architecture

How can i listen for Fragment change in my Activity?

I have an Activity which based on intent opens Fragment1 or Fragment2.
From the activity after some stuff are done if the user is in Fragment1 i replace the fragment to Fragment2 and that can be done even from the Fragment1 diretly.
For each Fragment i have to change items in my BottomAppBar, till i'm in Activity i have no problems with it as i've made just a function which changes the bottomAppBar items based on value passed it in.
The issue is when the .replace is called directly from the fragment.
So i tought if it was possible to set in anyway a 'FragmentListener' which listens for fragment change in my Activity and call that function from it..
My function looks like this:
private fun changeBottomBar(corpo: Boolean = false) {
if (corpo) {
binding.bottomAppBar.navigationIcon = ContextCompat.getDrawable(
this,
R.drawable.ic_baseline_menu_24
)
binding.bottomAppBar.menu.findItem(R.id.filter).isVisible = false
binding.bottomSheetTestata.titleBottomSheet.text = "Modifica Documento"
bottomSheetTestataBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
binding.bottomAppBar.menu.findItem(R.id.testata).isVisible = tipo != "Etichette"
}else {
binding.bottomAppBar.navigationIcon = null
binding.bottomAppBar.menu?.findItem(R.id.testata)?.isVisible = false
binding.bottomAppBar.menu?.findItem(R.id.filter)?.isVisible = true
binding.bottomSheetTestata.titleBottomSheet.text = "Nuovo Documento"
clearTestata()
bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
}
}
And i call it for every .replace where if the Fragment is Fragment2 i pass to it corpo = true
You can use EventBus Open source library for subscribing and publishing events.
https://greenrobot.org/eventbus/
For Publishing Event
//In fragment
EventBus.getDefault().post(new MessageEvent());
For Subscribing Event in Activity
//In Activity
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {/* Do something */};
Define you custom model class for event
public static class MessageEvent { /* Additional fields if needed */ }

Did Actually needs to add fragments in mainfest

override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
if (id ==R.id.refreshtabbutton){
val intent : Intent = Intent(this,frag2::class.java)
startActivity(intent)
}
return super.onOptionsItemSelected(item)
}
Error
android.content.ActivityNotFoundException: Unable to find explicit activity class {com.example.vlcclone/com.example.vlcclone.frag2}; have you declared this activity in your AndroidManifest.xml?
at com.example.vlcclone.MainActivity.onOptionsItemSelected(MainActivity.kt:54)
How to solve this issue? I want to open fragment when user clicks on the refresh button which is present in menu.
The fragments are not opened using Intents. You should create an activity that holds your second Fragment, or you should replace current fragment with the second (in case if you have container for holding the fragment inside your current activity). Intent is only for opening the Activity, not Fragment (!)
https://developer.android.com/guide/components/fragments go through this

Android: switch to a new fragment inside a fragment?

I have an Android application with a MainActivity and I do this to create navigational tabs in onCreate:
ActionBar myActionBar = getActionBar();
myActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Tab tab = myActionBar.newTab().setText("FirstTab").setIcon(R.drawable.first_tab)
.setTabListener(new TabListener<FirstTabFragment>(this, "FirstTab",
FirstTabFragment.class));
... more tabs ...
The TabListener, I use this from developer.android.com:
http://developer.android.com/reference/android/app/ActionBar.html#newTab():
public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
...
public TabListener(Activity activity, String tag, Class<T> clz) { ... }
}
So if a user clicks on the first tab, my fragment FirstTabFragment is called and executes onCreateView.
My problem is, if a user now clicks a button I do the following and I do not know how to switch to the next fragment:
private OnClickListener firstTabListener = new OnClickListener() {
#Override
public void onClick(View v) {
if (v == button1) {
Intent intent = new Intent(???, MyDetailsFragment.class);
startActivity(intent);
} else if (...) {
...
}
}
};
The MyDetailsFragmentshould show details to the selected item (button click), so I want to drill down to the details fragment and want to give some extra data to the new fragment, so the detail fragment knows which details of which selected item it should display.
The selected tab should not change and the back button should go back to the FirstTabFragment page.
I think I should start a new fragment, but it is not possible, the name of the method startActivity tells me that I start a new activity and not a fragment. So, I have to use the MainActivity and put into there the new fragment?
(I do not use the android-support-v4.jar library, because I only target Android 4 devices)
How can I solve this problem? Any ideas?
From the fragment, call a method on the hosting activity, telling it about the button click event. The activity can then do whatever is appropriate.
Personally, I think that totally replacing the contents of a tab is inappropriate in the vast majority of cases, but you are certainly welcome to do it.

Categories

Resources