Let me explain first: my application is planed to use 3 activities with swipe navigation. I am using different sherlock action bar for each one of them.
But since it is not possible to swipe between activities, the only solution is to work with fragments. I implemented that, but I came across a problem: is it possible to customize action bar for each fragment? Because now I'm stuck only with one. I've Googled and every solution is based on a menu, but is it possible to apply custom styles to menus and in fragments?
Sorry if this was already answered, I haven't found any solution online.
Is it possible to use this kind of approach?
public class ControlActivity extends SherlockFragmentActivity {
ActionBar actionBar;
View actionBarView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewpager_layout);
ViewPager pager = (ViewPager) findViewById(R.id.viewpager);
pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
actionBar = getSupportActionBar();
actionBarView= getLayoutInflater().inflate(
R.layout.friend_list_ab_layout, null);
actionBar.setCustomView(actionBarView);
}
private class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public SherlockFragment getItem(int pos) {
switch(pos) {
case 0:
actionBarView= getLayoutInflater().inflate(
R.layout.friend_list_ab_layout, null);
actionBar.setCustomView(actionBarView);
return MainActivity.newInstance();
case 1:
actionBarView= getLayoutInflater().inflate(
R.layout.news_feed_ab_layout, null);
actionBar.setCustomView(actionBarView);
return NewsFeed.newInstance();
default:
actionBarView= getLayoutInflater().inflate(
R.layout.friend_list_ab_layout, null);
actionBar.setCustomView(actionBarView);
return MainActivity.newInstance();
}
}
#Override
public int getCount() {
return 2;
}
}
}
well you can build your own action bar, what i mean to say is that you should create a dynamic fragment and use it at an action bar and give it styling a as action bar, use frame layout as a plcaeholder for the fragment and when you swipe the fragment replace the actionbar fragment with new one
Related
Actionbar.removealltabs removes all my tabs. However, the remaining space used to hold the tabs are still there. As a result my actionbar looks like a very tall actionbar with a empty bottom half.
Using support actionbar with appcompatactivity.
I've tried calling Actionbar.removealltabs in both my fragment and Mainactivity... same result.
Tabs pre-destruction
Tabs Destroyed, leaving behind it's empty space
How it originally looked before adding tabs. This is my desired result
Here's my Fragment that created the tabs.
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mViewPager = view.findViewById(R.id.reddit_search_pager);
mActionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
setViewPager();
setTabs();
}
public void setTabs() {
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
#Override
public void onTabSelected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
}
};
for (int i = 0; i < 3; i++) {
String tabTitle = "";
switch (i) {
case 0:
tabTitle = TAB_TITLE_SUBREDDITS;
break;
case 1:
tabTitle = TAB_TITLE_POSTS;
break;
case 2:
tabTitle = TAB_TITLE_USERS;
break;
}
mActionBar.addTab(
mActionBar.newTab()
.setText(tabTitle)
.setTabListener(tabListener));
}
}
Here's my primary MainActivity pre-existing modification's to the toolbar.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NetworkingUtils myClass = new NetworkingUtils(this);
ActionBar actionbar = getSupportActionBar();
actionbar.setDisplayHomeAsUpEnabled(true);
actionbar.setHomeAsUpIndicator(R.drawable.ic_action_menu);
When I am working with ListViews I usually use adapters. With adapters you have to call yourAdapter.notifyDataSetChaged() every time you make a new change on your list so the list can update normally. Maybe that is what is happening to you so try to call some method like the one I showed above and it will maybe update and clear the empty space.
I fixed it by using another way to use tabs, the Tablayout as described in this video. https://www.youtube.com/watch?v=zQekzaAgIlQ. I had to make my own Toolbar instead of the default theme one.
I have no idea why Android is suggesting a deprecated and buggy way to implement tabs on their official website instead of this. In fact, the TabLayout examples provided in the Youtube video are all 404 not found.
Background
I have an android app using fragments. I'm using a separate FragmentPagerAdapter (i.e. as a separate class, outside MainActivity).
MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.MainActivity);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(mViewPager);
}
SectionsPagerAdapter.java
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new frag1();
case 1:
return new frag2();
case 2:
return new frag3();
case 3:
return new frag4();
case 4:
return new frag5();
default:
return null;
}
}
#Override
public int getCount() {
return 5;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Name1";
case 1:
return "Name2";
case 2:
return "Name3";
case 3:
return "Name4";
case 4:
return "Name5";
}
return null;
}
The Issue
I need to refresh the view of, say, fragment #3 from fragment#2 (the ultimate goal is for changes the user initiates on fragment #2 to be visible as soon as the user proceeds to fragment#3. I have tried to detach/attach fragment #3 itself as soon as it is visible, like this:
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
getFragmentManager().beginTransaction().detach(this).attach(this).commit();
}
Unfortunately, a) this has a penalty in performance, as there is a "stutter" during navigation; b) it doesn't work reliably. Some things (the texts of some buttons) are not refreshed, for some reason I can't figure out.
In any case, I have discovered that the only 100% reliable method for forcing a refresh/redraw is to restart the activity (for example through an onClickListener on a Save button the user needs to press on the previous fragment, #2). But this restarts the Activity on fragment #1
My Question
How can I restart the activity on this specific fragment (#3), considering the fact I'm using a separate FragmentPagerAdapter?
I've studied several other questions/answers, for example this: https://stackoverflow.com/a/36064344
but how can I implement something like this (putting extras on the intent call) when the FragmentPagerAdapter is on a separate class? Alternatively, is there something else I can do to refresh the fragment view?
If you need extra info or code, let me know and I'd be glad to add clarification.
EDIT:
I managed to find another solution that so far seems to be working as intended. I added the following code on the onClickListener of the Save button on fragment #2
frag3 f3 = new frag3();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragmentContainer, f3);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
However, I'm still interested in my original question (how to start an activity on a specific fragment when using a separate FragmentPagerAdapter), so if you have any ideas about that, I'm all ears.
Well, wasn't that simple...
this.recreate(); not only restarts the activity but it also remembers the fragment position.
Just in case someone else needs this, when you're working from fragments you need to use it this way:
First declare the activity which contains the fragment in question. E.g.
public class frag1 extends Fragment {
...
Activity mactivity;
#Override
public void onAttach(Activity MainActivity) {
super.onAttach(MainActivity);
mactivity = MainActivity;
}
Then instead of getActivity().recreate(); simply use mactivity.recreate();
I am using MPAndroidChart library to make charts for an android application. I would like to make 3-4 charts and want to swipe them. Is it possible to have swipe functionality using MPAndroidChart library and how can I implement such swipe function?
I think by understanding your problem I may suggest two possible ways to do so.
1] Use horizontal recycler view and each row will have a chart to show and to do so create a list with custom model class.
2] Use ViewPager with Fragment:
To create a view pager pass your expected list of graphs and on every getItem create a new Fragment instance and attach it to viewpager.
Pass custom model class as a input values to render your chart through bundle using parcable or serializable interface.
Each fragment will have a chart to show.
Use a ViewPager and attach a FragmentStatePagerAdapter
public class SomePagerAdapter extends FragmentStatePagerAdapter {
int mNumOfTabs;
public MISPagerAdapter(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new LineChartFragment();
case 1:
return new BarChartFragment();
case 2:
return new PieChartFragment();
default:
return null;
}
}
#Override
public int getCount() {
return mNumOfTabs;
}}
Each Fragment will have its own dataset using which the charts will be drawn.
After I take my Photo and Signature, it displays on the ImageView. However, after I swap the tabs the ImageView returns to its default Image. See my screenshot.
There's no problem when it comes to editText the inputted value is still there. However, the ImageView is my problem. What's causing this problem? And how can I fix this?
Code:
public class RegisterUser extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.activity_register_user,container,false);
// Setting ViewPager for each Tabs
ViewPager viewPager = (ViewPager) v.findViewById(R.id.viewpager);
setupViewPager(viewPager);
// Set Tabs inside Toolbar
TabLayout tabs = (TabLayout) v.findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
// Create Navigation drawer and inlfate layout
return v;
}
// Add Fragments to Tabs
private void setupViewPager(ViewPager viewPager) {
Adapter adapter = new Adapter(getChildFragmentManager());
adapter.addFragment(new ListContentFragment(), "Info 1");
adapter.addFragment(new TileContentFragment(), "info 2");
adapter.addFragment(new CaptureSignatureActivity(), "info 3");
adapter.addFragment(new CardContentFragment(), "info 4");
viewPager.setAdapter(adapter);
}
static class Adapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public Adapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
When you swipe through tabs (Fragments, actually) in a TabLayout, the default behaviour is that the system kills the previous Fragment to free memory and the subsequent Fragment to the current one will be loaded in the memory.
Now, with your code something similar is happening. When you load a photo and a signature in the 3rd tab (CaptureSignatureFragment) and then swipe through the tabs, the CaptureSignatureFragment is killed and thus both the ImageViews have the default images set to them.
If you wish to keep the data in the 3rd tab intact even after changing tabs, you should better set your ViewPager's offscreen limit to 4 (no. of tabs you have) by:
viewPager.setOffscreenPageLimit(4)
Now, changing the tabs won't kill any of the fragments. However, doing this can create performance issues.
I have this weird issue with the viewPager. When I swipe from one fragment to the next and then swipe back, the layout is correct, but when pressing an element (Listview item for example), the previous java code still did not update with the view. I don't know if I can explain this any better, as it works when I play with the swipe until the fragment works like its supposed to. here is my code:
Main.Java:
public class Main extends FragmentActivity {
SectionsPagerAdapter mAdapter;
ViewPager mViewPager;
// for alert transitions
AlertDialog dialog;
// share button
private ShareActionProvider mShareActionProvider;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// set up button
getActionBar().setDisplayHomeAsUpEnabled(true);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// Create the adapter that will return a fragment for each of the three
// primary sections of the app.
mAdapter = new SectionsPagerAdapter(
getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mAdapter);
mViewPager.setPageTransformer(true, new DepthPageTransformer());
}
#Override
public void onBackPressed() {
if (mViewPager.getCurrentItem() == 0) {
// If the user is currently looking at the first step, allow the system to handle the
// Back button. This calls finish() on this activity and pops the back stack.
super.onBackPressed();
} else {
// Otherwise, select the previous step.
mViewPager.setCurrentItem(mViewPager.getCurrentItem() - 1);
}
}
}
SectionsPagerAdapter.java:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return new Important();
case 1:
return new Propositions();
case 2:
return new Information();
}
return null;
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return ("Important Dates").toUpperCase(l);
case 1:
return ("Props").toUpperCase(l);
case 2:
return ("Information").toUpperCase(l);
}
return null;
}
}
The Fragments all use the onCreateView() method.
Thanks in advance for your help!
Maybe a late response, but I've experienced the same issue.
The problem was the DepthPageTransformer you are using from the Android Developers example for PageTransformer.
There is a bug with stacking fragments and layer priority, I assume. By fixing the custom PageTransformer will fix your "swipe back" issue. Or if you don't mind the animation, just remove your custom PageTransformer and use the default animation (by adding nothing).