Adapt chrisbanes ActionBar-PullToRefresh to Fragments(NavigationDrawer) - android

Okay here is my problem:
I want to implement Chrisbanes ActionBar-PullToRefresh library with fragments to be able to use it with Navigationdrawer.
https://github.com/chrisbanes/ActionBar-PullToRefresh#fragments
.
Chrisbanes says this for the use with fragments:
One thing to note is that the PullToRefreshAttacher needs to be
created in the onCreate() phase of the Activity. If you plan on using
this library with Fragments then the best practice is for your
Activity to create the PullToRefreshAttacher, and then have your
fragments retrieve it from the Activity.
An example is provided in the Fragment & Tabs sample.
.
.
****Here comes the question:
I created the PullToRefreshAttacher in my activity but how the hell could I pass the PullToRefreshAttacher to my fragments :S****
I have read much about bundles and getArguments() with putSerializable and Parcelable :
Passing an Object from an Activity to a Fragment
and I also read this article in which sth. like this ((MyActivity ) getActivity()).getClassX() ; is used.
Call Activity Method From Fragment
But nothing I really understood/worked. :(
.
.
Here are the NavigationActivity and one example fragment.I have to say that I am new to android/Java :)
final String[] menuEntries = {"Start","Datum","Website","Kunden"};
final String[] fragments = {
"com.blabla.MainFragment",
"com.blabla.OneFragment",
"com.blabla.TwoFragment",
"com.blabla.KundenFragment",
};
private ActionBarDrawerToggle drawerToggle;
private DrawerLayout drawerAdapter;
private ListView navListAdapter;
private PullToRefreshAttacher mPullToRefreshAttacher;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.navigation_layout);
mPullToRefreshAttacher = PullToRefreshAttacher.get(this);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActionBar().getThemedContext(), android.R.layout.simple_list_item_1, menuEntries);
final DrawerLayout drawer = (DrawerLayout)findViewById(R.id.refresh_navwiev);
final ListView navList = (ListView) findViewById(R.id.drawerMenu);
drawerAdapter=drawer;
navListAdapter=navList;
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
drawerToggle = new ActionBarDrawerToggle(
this,
drawer,
R.drawable.navicon,
R.string.drawer_open,
R.string.drawer_close
) {
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
}
};
drawer.setDrawerListener(drawerToggle);
navList.setAdapter(adapter);
navList.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, final int pos,long id){
drawer.setDrawerListener( new DrawerLayout.SimpleDrawerListener(){
#Override
public void onDrawerClosed(View drawerView){
super.onDrawerClosed(drawerView);
//Runs On completly Closed
}
});
//Runs Onclick if not same fragment
if(getActionBar().getTitle()!= menuEntries[pos])
{
Bundle bundle=new Bundle();
bundle.putString("message", "From Activity");
//Fragment zusammenbauen
Fragment myFragment=new Fragment();
myFragment = Fragment.instantiate(NavigationActivity.this, fragments[pos]);
myFragment.setArguments(bundle);
FragmentTransaction tx = getSupportFragmentManager().beginTransaction();
tx.setCustomAnimations(R.anim.fragmentfadein, R.anim.fragmentfadeout);
tx.replace(R.id.navigationScreen, myFragment);
tx.commit();
getActionBar().setTitle(menuEntries[pos]);
drawer.closeDrawer(navList);
}
}
});
Bundle bundle=new Bundle();
// bundle.putInt(PullToRefreshAttacher., position);
//Fragment zusammenbauen
Fragment myFragment=new Fragment();
myFragment = Fragment.instantiate(NavigationActivity.this, fragments[0]);
myFragment.setArguments(bundle);
FragmentTransaction tx = getSupportFragmentManager().beginTransaction();
tx.setCustomAnimations(R.anim.fragmentfadein, R.anim.fragmentfadeout);
tx.replace(R.id.navigationScreen, myFragment);
tx.commit();
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU) {
Log.i("FlosTemplate", "Menu Taste Gedrückt");
if(drawerAdapter.isDrawerOpen(navListAdapter))
{
drawerAdapter.closeDrawer(navListAdapter);
}
else
{
drawerAdapter.openDrawer(navListAdapter);
}
return true;
}
return super.onKeyUp(keyCode, event);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
drawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (drawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
And a fragment
public class MainFragment extends Fragment {
public static Fragment newInstance(Context context) {
MainFragment f = new MainFragment();
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
It would be very kind if somebody could help me ,i am stuck at this point for days :)
P.S. sorry for the probably bad language , i am not a native speaker ;)

There is demo code on the GitHub page:
https://github.com/chrisbanes/ActionBar-PullToRefresh/blob/master/samples/actionbarcompat/src/java/uk/co/senab/actionbarpulltorefresh/samples/actionbarcompat/FragmentTabsActivity.java
Add this to your Activity:
public PullToRefreshAttacher getPullToRefreshAttacher() {
return mPullToRefreshAttacher;
}
And this to the onCreateView in your Fragment:
PullToRefreshAttacher mPullToRefreshAttacher = ((NavigationActivity) getActivity()).getPullToRefreshAttacher();
A better approach would be to use an interface but I'd recommend starting with the GitHub example.

Related

nested fragment throwing null

The end goal is to click from a list view stored in one fragment,
open another fragment that has a nested fragments view AnswerFragment,
here the nested fragments should consist of two fragments, top portion being the question text from the list and the bottom half being the answer. Right now I've managed to pull off the communication bit of passing the question text from the list to the single question fragment (which should be stored in the top half of the answer fragment) However it's inflating the single question layout over the answer fragment like this SingleQuestionFragment
.
public class MainActivity extends AppCompatActivity implements AllQsFragment.Communicator {
private DrawerLayout mDrawer;
private Toolbar toolbar;
private NavigationView mNVDrawer;
private ActionBarDrawerToggle drawerToggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Set a Toolbar to replace the ActionBar.
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerToggle = setupDrawerToggle();
mDrawer.setDrawerListener(drawerToggle);
//Find our drawer view
mNVDrawer = (NavigationView) findViewById(R.id.nvView);
//Setup drawer view
setupDrawerContent(mNVDrawer);
}
private ActionBarDrawerToggle setupDrawerToggle() {
return new ActionBarDrawerToggle(this, mDrawer, toolbar, R.string.drawer_open, R.string.drawer_close);
}
private void setupDrawerContent(NavigationView navigationView) {
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
selectDrawerItem(menuItem);
return true;
}
});
}
public void selectDrawerItem(MenuItem menuItem) {
//Creat a new fragment and specify the planet to show based on
//position
Fragment fragment = null;
Class fragmentClass;
switch (menuItem.getItemId()) {
case R.id.nav_first_fragment:
fragmentClass = AllQsFragment.class;
break;
default:
fragmentClass = AllQsFragment.class;
}
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
//Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flContent, fragment).addToBackStack("addedToBackStack").commit();
//Highlight the selected item, update the title, and close the drawer
menuItem.setChecked(true);
setTitle(menuItem.getTitle());
mDrawer.closeDrawers();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
//The action bar home/up action should open or close the drawer
switch (item.getItemId()) {
case android.R.id.home:
mDrawer.openDrawer(GravityCompat.START);
return true;
}
if (drawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
//Sync the toggle state after onRestoreInstanceState has occurred
drawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//Pass any configuration change to the drawer toggles
}
#Override
public void sendText(String data) {
SingleQuestionFragment questionFragment = (SingleQuestionFragment) getSupportFragmentManager().findFragmentByTag("fragmentQ");
if (questionFragment != null) {
questionFragment.changeText(data);
} else {
SingleQuestionFragment fragment = new SingleQuestionFragment();
Bundle args = new Bundle();
args.putString("text", data);
fragment.setArguments(args);
getSupportFragmentManager().beginTransaction()
.replace(R.id.flContent, fragment)
.addToBackStack(null).commit();
fragment.sentText();
}
}
}
fragment_answer
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.victor.nattest5.AnswerFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="#+id/q_fragment">
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="#+id/a_fragment">
</FrameLayout>
</LinearLayout>
AnswerFragment
public class AnswerFragment extends Fragment {
public AnswerFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
insertNestedFragment();
return inflater.inflate(R.layout.fragment_answer, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
private void insertNestedFragment() {
Fragment childQFragment = new SingleQuestionFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.q_fragment, childQFragment,
"fragmentQ").commit();
Fragment childAFragment = new SingleAnswerFragment();
FragmentTransaction transaction1 = getChildFragmentManager().beginTransaction();
transaction1.add(R.id.a_fragment, childAFragment, "fragmentA").commit();
}
public static final AnswerFragment newInstance() {
AnswerFragment frag = new AnswerFragment();
return frag;
}
}
SingleQuestionFragment
public class SingleQuestionFragment extends Fragment {
TextView questionTxt;
String stringtext;
public SingleQuestionFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_single_question, container, false);
questionTxt = (TextView) v.findViewById(R.id.textView_q);
return v;
}
public static final SingleQuestionFragment newInstance() {
SingleQuestionFragment frag = new SingleQuestionFragment();
return frag;
}
public void changeText(String data) {
questionTxt.setText(data);
}
public void sentText() {
new BackGroundTask().execute();
}
private class BackGroundTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... strings) {
Bundle b = getArguments();
stringtext = b.getString("text");
return null;
}
protected void onPostExecute(String result){
changeText(stringtext);
}
}
}
When I run this with the debugger, the app runs without crashing. However, it shows this line is null ->
SingleQuestionFragment questionFragment = (SingleQuestionFragment) getSupportFragmentManager().findFragmentByTag("fragmentQ");
I know what null means, I just don't understand how to fix this problem. Somewhere in my code I think I'm inflating an extra layout or possibly inflating the wrong container.
It's hard to offer any suggestions because your app is complex and not all of the code is posted. It's also not clear whether any of the posted code includes changes you've made to try and work around the problem. For example, I don't understand the need for BackGroundTask. There is no reason to perform that processing in a background thread. Did you do this as a workaround to add some delay to the processing?
You didn't post the code that calls MainActivity.sendText(), or explain what causes it to be called.
If I understand your post correctly, in sendText(), the call to findFragmentByTag() is returning null and that is an error. Are you expecting to find the SingleQuestionFragment added in AnswerFragment? If so, you won't find it because you are searching the fragments held by the manager of MainActivity only. The search does not include fragments held by the managers of child fragments. In other words, the search does not recursively search the fragment tree.

Navigation Drawer AsyncTask

I would like to expose my problem and I want to know how I could solve it.
In my application I'm using an activity, making a simple login, launching a asyncTask. At the end of this task, the user is redirected to another activity, which is the home activity of application. The latter has the task of managing a navigation drawer and its fragments. The contents of each fragment must be populated with data retrieved from a server and the navigation drawer set the default fragment F1, which is displayed after the user has logged on.
Now the problem is:
How can I recover the data necessary to populate the listView contained in fragment1?
I know how to implement an adapter for the listView, but I don't understand how to communicate the home activity with the fragment F1. My intention would be to retrieve a circular dialog (content in F1) and run it as long as the data required for the adapter have not been recovered.
Here some code:
public class LoginActivity extends ActionBarActivity {
private Button loginButton;
private ProgressDialog progressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
loginButton = (Button) findViewById(R.id.login_button);
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new Login().execute();
}
};
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class Login extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(LoginActivity.this);
progressDialog.setMessage("Login");
progressDialog.setCancelable(false);
progressDialog.show();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (progessDialog.isShowing()) {
progressDialog.dismiss();
}
Intent intent = new Intent(getApplicationContext(), HomeActivity.class);
Bundle bundle = new Bundle();
intent.putExtras(bundle);
startActivity(intent);
}
#Override
protected Void doInBackground(String... params) {
// code to retrieve data.
}
}
}
public class HomeActivity extends ActionBarActivity implements FragmentDrawer.FragmentDrawerListener {
private Toolbar toolbar;
private FragmentDrawer fragmentDrawer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(false);
fragmentDrawer = (FragmentDrawer) getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
fragmentDrawer.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), toolbar);
fragmentDrawer.setDrawerListener(this);
// Here the problem!!!
displayView(0);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_home, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void displayView(int position) {
switch (position) {
case 0:
Fragment fragmentOne = new FragmentOne();
move(matchFragment);
break;
case 1:
Fragment fragmentTwo = new FragmentTwo();
move(teamFragment);
break;
case 2:
Fragment fragmentThree = new FragmentThree();
move(myTeamFragment);
break;
case 3:
//other fragment....
default:
break;
}
}
public void move (Fragment fragment) {
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment, fragment.getClass().getSimpleName());
fragmentTransaction.commit();
}
}
#Override
public void onDrawerItemSelected(View view, int position) {
displayView(position);
}
}
public class FragmentOne extends Fragment {
private ListView listView;
private ArrayList<Info> infos;
private InfoAdapter infoAdapter;
public FragmentOne() {}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_match, container, false);
listView = (ListView) rootView.findViewById(R.id.match_list_view);
return rootView;
}
}
Now, where do I implement the AsyncTask to retrieve data for adapter? In fragment or the Activity?
If it were the Activity, how can I recover the elements of view of fragment?
Thanks in advance and sorry for bad english.
for your first quesiton:
I don't understand how to communicate the home activity with the
fragment F1
You can pass information from HomeActivity to the Fragment through parameters passed to the Fragment's constructors. So instead of Fragment fragmentOne = new FragmentOne();, you can call Fragment fragmentOne = new FragmentOne(A a); where a is data you want to pass to the fragment. Of course, you need to add in the constructor with parameters to the Fragment class.
For the 2nd point:
Now, where do I implement the AsyncTask to retrieve data for adapter?
In fragment or the Activity? If it were the Activity, how can I
recover the elements of view of fragment?
You can put AsynchTask call inside onCreate() to load data for the listView...etc. Another option which I prefer is to use Loaders. Please see this documentation on Loaders here http://developer.android.com/guide/components/loaders.html. It also has an example.
For explanation and sample, you can follow these 4-part tutorials:
http://www.androiddesignpatterns.com/2012/07/loaders-and-loadermanager-background.html.

Android master / detail fragment with back button

I implemented a Drawer in the Main FragmentActivity, but don't know how to add a back navigation button in master/detail fragment.... Find several days still no answer.... any expert can help?
>> MainActivity with Drawer
public class MainActivity extends FragmentActivity {
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTitle = mDrawerTitle = getTitle();
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
CreateMenuItem();
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// toggle nav drawer on selecting action bar app icon/title
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action bar actions click
switch (item.getItemId()) {
case R.id.action_settings:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
private void displayView(int position) {
switch (position) {
case 0:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_frame, FragmentA.newInstance(), FragmentA.TAG).commit();
break;
case 1:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_frame, FragmentB.newInstance(), FragmentB.TAG).commit();
break;
case 2:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_frame, FragmentC.newInstance(), FragmentC.TAG).commit();
break;
case 3:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_frame, FragmentD.newInstance(), FragmentD.TAG).commit();
break;
default:
break;
}
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
mDrawerLayout.closeDrawer(mDrawerList);
}
}
>> Fragment A (Master Fragment)
public class FragmentA extends Fragment {
public FragmentA(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragmentA, container, false);
Button button= (Button) rootView.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentDetail fd = new FragmentDetail();
android.support.v4.app.FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragmentdetail, fd);
ft.setTransition(android.support.v4.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
});
return rootView;
}
>> FragmentDetail (Detail Fragment) > How to add a back button instead the navigator drawer menu
public class FragmentDetail extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_detail, container, false);
return rootView;
}
}
I implemented a Drawer in the Main FragmentActivity, but don't know how to add a back navigation button in master/detail fragment.... Find several days still no answer.... any expert can help?
/**
* Handling back press of all fragments (Use this in fragmentactivity)
*
* */
#Override
public void onBackPressed() {
super.onBackPressed();
}
I usually set an onKeyListener to the View in onResume. From what I learned you have to take care to set setFocusableInTouchMode() and requestFocus on the View.
This is a sample of what I use for this purpose:
#Override
public void onResume() {
super.onResume();
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){
// handle back button
getActivity().getSupportFragmentManager().popBackStack();
return true;
}
return false;
}
});
}

Android refresh a fragment list from its parent activity

I have a main activity which contains the action bar with 3 menu buttons in it.
I then have a fragment within this main activity which has a list.
I would like to be able to refresh the list in the fragment from the main activity, when one of the menu buttons is clicked, or preferably just removed all the rows from the list.
Any help is appreciated.
Thanks.
public class Favourite extends SherlockFragmentActivity {
ActionBar actionBar;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.favourite);
actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(false);
BitmapDrawable bg = (BitmapDrawable)getResources().getDrawable(R.drawable.actionbar_bg);
bg.setTileModeX(TileMode.REPEAT);
getSupportActionBar().setBackgroundDrawable(bg);
getSupportActionBar().setIcon(R.drawable.favourite_title);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tabAll = actionBar.newTab();
ActionBar.Tab tabfavs = actionBar.newTab();
ActionBar.Tab tabhist = actionBar.newTab();
tabAll.setText("all");
tabfavs.setText("favs");
tabhist.setText("hist");
tabAll.setTabListener(new MyTabListener());
tabfavs.setTabListener(new MyTabListener());
tabhist.setTabListener(new MyTabListener());
actionBar.addTab(tabAll);
actionBar.addTab(tabfavs);
actionBar.addTab(tabhist);
try{
}
catch(Exception e)
{
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.actionbar_itemlist_favourite, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.history:
break;
case R.id.favourite:
Intent favAct = new Intent(this, Favourite.class);
startActivity(favAct);
break;
case R.id.delete:
///I WANT TO BE ABLE TO REFRESH FRAGMENTLIST FROM HERE
}
return true;
}
}
class MyTabListener implements ActionBar.TabListener {
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if(tab.getPosition()==0)
{
FavouriteAllWords frag = new FavouriteAllWords();
ft.replace(android.R.id.content, frag);
}
else if(tab.getPosition()==1)
{
FavouriteFavWords frag = new FavouriteFavWords();
ft.replace(android.R.id.content, frag);
}
else if(tab.getPosition()==2)
{
FavouriteHistWords frag = new FavouriteHistWords();
ft.replace(android.R.id.content, frag);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
}
////////////////////MY LIST FRAGMENT CLASS
public class FavouriteAllWords extends ListFragment {
ArrayAdapter<String> adapter;
List<String> stringOfFavWords;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup group, Bundle saved)
{
adapter = new ArrayAdapter<String>(
inflater.getContext(), R.layout.row, stringOfFavWords);
setListAdapter(adapter);
return super.onCreateView(inflater, group, saved);
}
#Override
public void onActivityCreated (Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
}
}
You can easily achieve this using INTERFACE
MainActivity.java
public class MainActivity extends Activity {
public FragmentRefreshListener getFragmentRefreshListener() {
return fragmentRefreshListener;
}
public void setFragmentRefreshListener(FragmentRefreshListener fragmentRefreshListener) {
this.fragmentRefreshListener = fragmentRefreshListener;
}
private FragmentRefreshListener fragmentRefreshListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b = (Button)findViewById(R.id.btnRefreshFragment);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(getFragmentRefreshListener()!=null){
getFragmentRefreshListener().onRefresh();
}
}
});
}
public interface FragmentRefreshListener{
void onRefresh();
}
}
MyFragment.java
public class MyFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = null; // some view
/// Your Code
((MainActivity)getActivity()).setFragmentRefreshListener(new MainActivity.FragmentRefreshListener() {
#Override
public void onRefresh() {
// Refresh Your Fragment
}
});
return v;
}
}
Just make your update/refresh method public and call it from your Activity.
OR
Use LocalBroadcastManager or EventBus to send event from your Activity, and by subscribing to this event in a Fragment - react to it and call refresh/update method.
Your activity can call methods in the fragment by acquiring a reference to the Fragment.
(1) Provide a tag when you add your fragment.
transaction.add(R.id.fragment_container, myFragment, "myfragmentTag");
(2) In your hosting activity you can find the fragment and have access to it's methods.
FragmentManager fm = getSupportFragmentManager();
myFragment f = (myFragment) fm.findFragmentByTag("myfragmentTag");
f.refreshAdapter()
(3) refreshAdapter() could now call adapter.notifyDataSetChanged().
This is one of the recommended ways to communicate up to a fragment.
The interface implementation is mainly for communicating back to the activity.
Biraj Zalavadia's answer is 100% right, you will call nay fragment methods from using interface....
this interface methods is running without error...
use this in MainActivity above oncreate
private FragmentRefreshListener fragmentRefreshListener;
public FragmentRefreshListener getFragmentRefreshListener() {
return fragmentRefreshListener;
}
public void setFragmentRefreshListener(
FragmentRefreshListener fragmentRefreshListener) {
this.fragmentRefreshListener = fragmentRefreshListener;
}
inside of Activity
private void refreshcall(String result2) {
// TODO Auto-generated method stub
if (getFragmentRefreshListener() != null) {
getFragmentRefreshListener().onRefresh(result2);
}
}
and put this in needed Fragment
private FragmentRefreshListener fragmentRefreshListener;
public FragmentRefreshListener getFragmentRefreshListener() {
return fragmentRefreshListener;
}
public void setFragmentRefreshListener(
FragmentRefreshListener fragmentRefreshListener) {
this.fragmentRefreshListener = fragmentRefreshListener;
}
Communicating with Other Fragments
http://developer.android.com/training/basics/fragments/communicating.html
This can also be used to communicate between an Activity and a Fragment.
When you click on ActionBar any Button then call interface to refresh the ListFragment. Because in java interface is used for inter-communication.
In Kotlin
Get the list of Support Fragment from the activity and check Instance and then call fragment function
val fragments = supportFragmentManager.fragments
for (fragment in fragments) {
if (fragment is HomeCategoriesFragment) {
fragment.updateAdapter() // Define function in Fragment
}
}

Using backstack and back button in viewpager

I'm using a viewpager to swipe between fragments and would like the back button to navigate to the previously viewed fragment rather than ending the activity. Sorry if this is a duplicate of this question however I didn't find the answer very helpful. Obviously onBackPressed needs to be overridden, but I don't know how to get and display the correct fragment. I assume that I should use the fragmentmanager's backstack, but getSupportFragmentManager().getBackStackEntryCount() always returns 0. Do I need to manually add fragments to the backstack using FragmentTransaction.addToBackStack()? If so, where would I add this in my adapter?
Here is the code for my activity,
public class PagerActivity extends FragmentActivity {
ArrayList<Sale> sales;
MyAdapter mAdapter;
ViewPager mPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent it = getIntent();
this.sales = (ArrayList<Sale>) it.getExtras().get("sales");
int position = it.getExtras().getInt("position");
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.fragment_pager);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mPager.setCurrentItem(position);
}
public class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public int getCount() {
return sales.size();
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
#Override
public Fragment getItem(int position) {
SalesThumbFragment frag = new SalesThumbFragment();
return frag.newInstance(sales.get(position));
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.sales_controller, menu);
return true;
}
#Override
public void onBackPressed() {
if(getSupportFragmentManager().getBackStackEntryCount() != 0) {
getSupportFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
}
In new design support library, i use this
I have same issue and i follow this step
In the main activity where there are 3 fragment in viewpager i create stack
and push and pop data.
//private Stack<Integer> stackkk; ==> As i get edit suggestion
private Stack<Integer> stackkk = new Stack<>(); // Edited
private ViewPager mPager;
private int tabPosition = 0;
mTabLayout.setupWithViewPager(mPager);
mPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
tabPosition = tab.getPosition();
mPager.setCurrentItem(tab.getPosition());
if (stackkk.empty())
stackkk.push(0);
if (stackkk.contains(tabPosition)) {
stackkk.remove(stackkk.indexOf(tabPosition));
stackkk.push(tabPosition);
} else {
stackkk.push(tabPosition);
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
tabPositionUnselected = tab.getPosition();
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
and in the onBackPressed in activity,
#Override
public void onBackPressed() {
if (stackkk.size() > 1) {
stackkk.pop();
mPager.setCurrentItem(stackkk.lastElement());
} else {
}
}
Use this code in Fragment Activity class. Don't forget to add return true;
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
mViewPager.setCurrentItem(viewPageSelected - 1);
return true;
}
return super.onKeyDown(keyCode, event);
}
I had a similar problem, this is how I solved it. I think you can adapt the code to your problem, if I understood what you problem is. I had a ViewPager with 6 fragments and wanted to keep track of the page history and to be able to use the back button to navigate backwards in the history. I create a java.util.Stack<Integer> object, add fragment numbers to it (except when you use the back button, see below), and override onBackPressed() to make it pop the last viewed fragment instead of using the back stack, when my history stack is not empty.
You want to avoid pushing elements on the Stack when you press the back button, otherwise you will get stuck between two fragments if you keep using the back button, instead of eventually exiting.
My code:
MyAdapter mAdapter;
ViewPager mPager;
Stack<Integer> pageHistory;
int currentPage;
boolean saveToHistory;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.container);
mPager.setAdapter(mAdapter);
mPager.setOffscreenPageLimit(5);
pageHistory = new Stack<Integer>();
mPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int arg0) {
if(saveToHistory)
pageHistory.push(Integer.valueOf(currentPage));
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
saveToHistory = true;
}
#Override
public void onBackPressed() {
if(pageHistory.empty())
super.onBackPressed();
else {
saveToHistory = false;
mPager.setCurrentItem(pageHistory.pop().intValue());
saveToHistory = true;
}
};
If you use a field to keep track of the index of the previous page using mPager.getCurrentItem() after each time the user navigates to a new fragment, then in the onBackPressed() method, you should be able to call mPager.setCurrentItem(previousPage)
Or, if the user can only page in order, then you don't need a field at all, and you could just do mPager.setCurrentItem(mPager.getCurrentItem()-1)
I've made custom ViewPager and implement stack functionality in it.
public class CustomViewPager extends ViewPager {
private Stack<Integer> stack = new Stack<>();
#Override
public void setCurrentItem(int item, boolean smoothScroll) {
stack.push(getCurrentItem());
super.setCurrentItem(item, smoothScroll);
}
public int popFromBackStack(boolean smoothScroll) {
if (stack.size()>0) {
super.setCurrentItem(stack.pop(), smoothScroll);
return getCurrentItem();
} else return -1;
}

Categories

Resources