I using Fragment set cameraView
There is an error this onResume
#Override
public void onResume() {
super.onResume();
if (isCameraAccessGranted() && isRecordAudioGranted() && isWriteStorageGranted()) {
cvCamera.start();
} else {
ActivityCompat.requestPermissions(getActivity(), VIDEO_PERMISSIONS, 0);
}
}
I doing Stepper 5 Page Fragment this is PagerAdapter
public class PagerAdapter extends FragmentStatePagerAdapter {
public PagerAdapter(FragmentManager supportFragmentManager, int behavior) {
super(supportFragmentManager, behavior);
}
#Override
public int getCount() {
return 6;
}
#Override
public Fragment getItem(int position) {
return new BlankFragmentTestCamera();
}
#Override
public CharSequence getPageTitle(int position) {
return "Page " + position;
}
}
Please help me.
ViewPager by default keeps previous and next fragment in the resumed state. So it's like one camera opened on three screens at the same time.
Please, try to
Use only 1 fragment with camera view
Use flag FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT for the ViewPager
I've prepared a small working demo, please, take a look
https://github.com/3akat/Ziggeo_CameraView_PagerDemo
Related
In my MainActivity, I have:
#Override
protected void onResume() {
super.onResume();
checkForCrashes();
checkForTutorial();
checkForUpdates();
setStore();
setup();
}
In setup(), I call initializeTabs() in a callback:
protected void setup() {
final Store s = getStore();
setBackground();
if (s == null) {
unauthorizedHandler();
return;
}
final Context mainActivity = this;
fragments = getTabFragments();
StoresController.getStoreDetails(s, mainActivity, new Callback<StoreDetailDecorator>() {
#Override
public void success(StoreDetailDecorator storeDetailDecorator, Response response) {
s.prettyName = storeDetailDecorator.store.pretty_name;
s.save();
Log.v(TAG, s.prettyName);
TextView toolbar_label = (TextView)findViewById(R.id.toolbar_label);
toolbar_label.setText(MainActivity.getTruncatedMenuName(s.name()));
SummaryTab t1 = (SummaryTab)fragments.get(0);
t1.notifier = (SummaryTabLoadingNotifier)mainActivity;
initializeTabs(s, fragments);
t1.populateReport();
}
}
}
public void initializeTabs(Store s, List<Fragment> fragments ) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager(), getTabTitles(), fragments);
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setOffscreenPageLimit(2);
pager.setAdapter(adapter);
}
That last line is crashing for some customers.
java.lang.IllegalStateException: Fragment InfoTab{1bcb80f} is not currently in the FragmentManager
But not every time. Why would this happen sometimes? Something to do with the fragment not being connected? I read some things about checking isAdded() on a fragment, but that's for checking if a fragment is added to an Activity. I'm using a FragmentStatePagerAdapter :
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private CharSequence[] titles;
private List<Fragment> fragmentList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fragmentManager, CharSequence titles[], List<Fragment> fragmentList) {
super(fragmentManager);
this.titles = titles;
this.fragmentList = fragmentList;
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public CharSequence getPageTitle(int position) { return titles[position]; }
#Override
public int getCount() { return fragmentList.size(); }
#Override
public Parcelable saveState() {
return null;
}
}
Could saveState(){ return null;} be it? This is there, as I understand things, to ensure the view is refreshed every time.
onResume() is called every time your activity returns to foreground.
If one of your users, for example, presses the home button and returns to your app then getStoreDetails() will be called again and you'll create a new adapter (with the same old fragment list) when the result arrives.
You should instantiate your fragments, create an adapter and populate your viewpager with the adapter only once (onCreate() would be the spot).
When new data arrives from getStoreDetails() just update the already added fragments with the new data.
This is because you are returning null in saveState(). You shouldn't try to override this behavior.
But even if you want to do it for some reason, you have to override public void restoreState(Parcelable state, ClassLoader loader) as well to avoid crash, because that method is relying on data saved in saveState().
But I would suggest you to not override it at all, and instead explain what you wanted to achieve there.
I have problem that it takes long time to load data and show only when i scroll the view pager. Several time i already used asynctask but not work. After changing tab, i called same fragment any one help me??
Here, is first time loaded data
After changing tab call same fragment
Here is my Adapter for ViewPager
public class AdapterCategoryViewPager extends FragmentPagerAdapter {
Context context;
private List<Fragment> fragmentList;
private List<Type> typeList;
public AdapterCategoryViewPager(FragmentManager fm, Context context, List<Fragment> fragmentList, List<Type> typeList) {
super(fm);
this.context = context;
this.fragmentList = fragmentList;
this.typeList = typeList;
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public CharSequence getPageTitle(int position) {
return typeList.get(position).getType().toString();
}
#Override
public int getCount() {
return fragmentList.size();
}
}
Here is my Fragment for category this function i call on async task
private void setData(View v)
{
addWomenCategory();
ll_list.removeView(v);
gridView.removeView(v);
gridView.setMode(PullToRefreshBase.Mode.PULL_FROM_END);
adapterCategory=new AdapterCategory(v.getContext(),categoryArrayList,height,width);
gridView.setAdapter(adapterCategory);
g=(GridView) gridView.getRefreshableView();
g.setHorizontalSpacing(h7);
g.setVerticalSpacing(h7);
// g.setEnabled(false);
gridView.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener<GridView>() {
#Override
public void onRefresh(final PullToRefreshBase<GridView> refreshView) {
gridView.postDelayed(new Runnable() {
#Override
public void run() {
refreshView.getLoadingLayoutProxy().setRefreshingLabel("Loding Data...");
refreshView.getLoadingLayoutProxy().setReleaseLabel("Refresh complete");
addWomenCategory();
adapterCategory.notifyDataSetChanged();
gridView.setRefreshing(false);
gridView.onRefreshComplete();
}
},2000);
}
});
}
Here is my HomeFragment which actually add fragments category in array list this function i also called in asynctask
private void setData(View v)
{
addType();
pager.setOffscreenPageLimit(3);
adapterType=new AdapterType(typeArrayList,v.getContext(),height,width);
fragmentList.add(new FragmentListCategory());
fragmentList.add(new FragmentMenListCategory());
fragmentList.add(new FragmentKidListCategory());
fragmentList.add(new FragmentListCategory());
fragmentList.add(new FragmentMenListCategory());
fragmentList.add(new FragmentKidListCategory());
pager.setAdapter(new AdapterCategoryViewPager(getFragmentManager(),v.getContext(),fragmentList,typeArrayList));
tabs.setViewPager(pager);
setUpTabStrip(v);
}
I have used universal imageloader library to display image and i was initialized its object every time in adapter to solve this issue i initialize that configuration object only once in whole application in main activity's onCreate() method
As addWomenCategeory() being an asynchronous task, the code in the main thread doesn't wait for the result.
Consider moving the code
adapterCategory.notifyDataSetChanged(); gridView.setRefreshing(false); gridView.onRefreshComplete();
to addWomencategory() method, where you recieve result from your back-end
As many applications I have MainActivity with ViewPager.
When I select option in NavigationDrawer I want to change one fragment in ViewPager. So to achieve that I created something like this:
Option click listener:
#Override
public void onItemClick(View view, int pos) {
mainActivity.changeFragment(pos);
}
MainActivity method:
public void changeFragment(final int key) {
mDrawerLayout.closeDrawers();
new Handler(Looper.getMainLooper()).post(new Runnable(){
#Override
public void run() {
mainPagerAdapter.setKey(key);
}
});
}
And MainPagerAdapter:
public class MainPagerAdapter extends FragmentStatePagerAdapter {
public final static int NUM_OF_PAGES = 2;
private int mCurrentFragmentKey = 0;
public MainPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == HOME) {
if (mCurrentFragmentKey == 0)
return new Fragment1();
else
return new Fragment2();
} else
return new SecondViewPagerFragment();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return NUM_OF_PAGES;
}
public void setKey(int key) {
mCurrentFragmentKey = key;
notifyDataSetChanged();
}
Question:
Unfortunately it's not working properly because when I select option whole view stutters giving bad performance. How can I fix that?
Edit
I changed notifying pager that data set changed into this:
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
mainPagerAdapter.setKey(key);
}
}, 500);
And now everything works fine, but I'm not sure that is best solution. Could someone help me with this?
What about if you have various adapter that extends FragmentStatePagerAdapter and when you need to change the contents in the viewpager, you simple call pager.setAdapter(anotherAdapter)?
If setAdapter supply the views to be shown, changing the adapter probably will make the content of your viewpager change.
I'm trying to get SlidingMenu to work alongside ViewPager and I have followed the examples inside the library to the letter. The source for my Activity can be found bellow.
The problem is that despite the fact that the SlidingMenu and ViewPager work fine together there is this problem that after opening the SlidingMenu for the first time and closing it afterwards the ViewPager starts acting weird.
By weird I mean when you swipe to right and left the UI gets stuck on one page and doesn't change and I mean it's only the UI as I can see in the logger that the pages actually change.
I have searched the web extensively and although there has been a lot of similar problems with implementing SlidingMenu alongside ViewPager, my problem seems to be unique.
Any help is appreciated.
public class MainTabActivity extends SlidingFragmentActivity {
private static final String TAG = "MainTabActivity";
#InjectView(R.id.tabHostPager)
ViewPager tabHostPager;
#InjectView(R.id.tabs)
PagerSlidingTabStrip tabStrip;
FragmentPagerAdapter pagerAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_tab);
setBehindContentView(R.layout.sliding_menu_layout);
loadSlidingMenu();
ButterKnife.inject(this);
pagerAdapter = new MainTabAdapter(getSupportFragmentManager());
tabHostPager.setAdapter(pagerAdapter);
//Assign the TabStrip it's ViewPager
tabStrip.setViewPager(tabHostPager);
tabStrip.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
switch (position) {
case 0:
getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
break;
default:
getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
break;
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
tabHostPager.setCurrentItem(0);
}
private void loadSlidingMenu() {
// configure the SlidingMenu
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
getSlidingMenu().setMode(SlidingMenu.LEFT);
getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
getSlidingMenu().setShadowWidth(100);
getSlidingMenu().setFadeDegree(0.35f);
getSlidingMenu().setBehindWidth(width / 100 * 90);
}
private class MainTabAdapter extends FragmentPagerAdapter {
public MainTabAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 4;
}
#Override
public Fragment getItem(int position) {
return Friends.newInstance();
}
#Override
public CharSequence getPageTitle(int position) {
return "Home";
}
}
}
Finally I managed to solve it. It had something to with manageLayers method from the SlidingMenu class.
Commenting out the method body was all it took:
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void manageLayers(float percentOpen) {
/*if (Build.VERSION.SDK_INT < 11) return;
boolean layer = percentOpen > 0.0f && percentOpen < 1.0f;
final int layerType = layer ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE;
if (layerType != getContent().getLayerType()) {
getHandler().post(new Runnable() {
public void run() {
Log.v(TAG, "changing layerType. hardware? " + (layerType == View.LAYER_TYPE_HARDWARE));
getContent().setLayerType(layerType, null);
getMenu().setLayerType(layerType, null);
if (getSecondaryMenu() != null) {
getSecondaryMenu().setLayerType(layerType, null);
}
}
});
}*/
}
I need to change a TextView's text that is placed in the layout of my FragmentActivity that has a ViewPager and a ViewPagerAdapter. Basically I have created an action bar in my application that presents the name of the current visible Fragment.
So I need this TextView to be changed on each change of the visible fragment in the ViewPager (either with the swipe motion or selected using the TabHost). From my search I found that this method should help me achieve my goal:
#Override
public void setUserVisibleHint(boolean isVisibleToUser)
{
Log.d(TAG, "setUserVisibleHint invoked!");
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser)
{
if (odTab != null && getActivity() != null)
{
Log.d(TAG, "Currently visable tab: "+odTab.getTabTitle());
Toast.makeText(getActivity(), "Currently visable tab: "+odTab.getTabTitle(), Toast.LENGTH_LONG).show();
if (application.getCurrentDataSource() == DataSource.SSRS)
{
if (rsTab.getTabTitle().equals("") || rsTab.getTabTitle() == null)
{
tabName.setVisibility(View.GONE);
}
else
{
tabName.setText(rsTab.getTabTitle());
}
}
else if (application.getCurrentDataSource() == DataSource.SGRDL)
{
Log.d(TAG, "found Title textView from fragmentActivity");
if (odTab.getTabTitle().equals("") || odTab.getTabTitle() == null)
{
((TabsViewPagerFragmentActivity)getActivity()).findViewById(R.id.tvTabName).setVisibility(View.GONE);
}
else
{
Log.d(TAG, "set Title textView to: "+odTab.getTabTitle());
((TextView) ((TabsViewPagerFragmentActivity)getActivity()).findViewById(R.id.tvTabName)).setText(odTab.getTabTitle());
}
}
}
}
}
I tried to implement it in my fragment but for some reason this line:
((TextView) ((TabsViewPagerFragmentActivity)getActivity()).findViewById(R.id.tvTabName)).setText(odTab.getTabTitle());
doesn't do anything although this line do get presented in the log for each change of fragment in the viewPager:
Log.d(TAG, "set Title textView to: "+odTab.getTabTitle());
UPDATE:
My adapter:
public class ViewPagerAdapter extends FragmentPagerAdapter
{
private List<Fragment> fragments;
/**
* #param fm
* #param fragments
*/
public ViewPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
/* (non-Javadoc)
* #see android.support.v4.app.FragmentPagerAdapter#getItem(int)
*/
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
/* (non-Javadoc)
* #see android.support.v4.view.PagerAdapter#getCount()
*/
#Override
public int getCount() {
return this.fragments.size();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
Am I doing something wrong? is there another way to do this operation?
In your activity you can do:
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int pos) {
// Change your textview
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
#Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
});
Although I can't pinpoint the problem, I would suggest to simplify your code:
avoid cast within cast. You use TabsViewPagerFragmentActivity both in if and else. assign this cast to a parameter and use this parameter. The processing overhead worth it.
instead of using findViewById, save R.id.tvTabName as a local parameter in TabsViewPagerFragmentActivity and create a method setTitle(String title) in TabsViewPagerFragmentActivity. It will also help you to debug this call at the activity itself.
I agree with #mromer - try to access the fragment from the activity. To achieve this, make your FragmentPagerAdapter inherit the following class:
public abstract class SmartFragmentPagerAdapter extends FragmentPagerAdapter {
private SparseArray<String> mFragmentTags;
private FragmentManager mFragmentManager;
public SmartFragmentPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
mFragmentManager = fragmentManager;
mFragmentTags = new SparseArray<String>();
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Object obj = super.instantiateItem(container, position);
if (obj instanceof Fragment) {
// record the fragment tag here.
Fragment f = (Fragment) obj;
String tag = f.getTag();
mFragmentTags.put(position, tag);
}
return obj;
}
// use this method in onPageSelected
public Fragment getFragment(int position) {
String tag = mFragmentTags.get(position);
if (tag == null)
return null;
return mFragmentManager.findFragmentByTag(tag);
}
public FragmentManager getFragmentManager() {
return mFragmentManager;
}
}
The way I finally managed to deal with this issue is combined with a few things:
1. First I declared an interface in my fragment:
public interface OnFragmetVisibleListener{
public void fragmetVisible(boolean visible);
}
2. Next I added this function as well to the fragment to know when it's attached to the ViewPager:
#Override
public void onAttach(Activity activity){
super.onAttach(activity);
try{
onFragmetVisibleListener = (OnFragmetVisibleListener) activity;
isAttached = true; //flag for whether this framgnet is attache to pager
} catch (ClassCastException e){
throw new ClassCastException(activity.toString() + " must implement interface OnFragmetVisibleListener");
}
}
3. I added the following method as well to know when the fragment is visible and set it's data object in the Application class:
#Override
public void setUserVisibleHint(boolean isVisibleToUser)
{
Log.d(TAG, "setUserVisibleHint invoked!");
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser)
{
if (odTab != null && getActivity() != null)
{
Log.d(TAG, "Currently visable tab: "+odTab.getTabTitle());
application.currentVisibleTab = odTab;
}
if (isAttached)
{
onFragmetVisibleListener.fragmetVisible(true);
}
}
}
4. In my ViewPager's activity I let it implement the defined interface in step 1:
public class TabsViewPagerFragmentActivity extends FragmentActivity implements GridFragment.OnFragmetVisibleListenerr
5. Next I added the unimplemented method:
#Override
public void fragmetVisible(boolean visible)
{
if(visible)
{
setCurrentTabTitle(application.currentVisibleTab.getTabTitle());
}
}
6. when setCurrentTabTitle is:
public void setCurrentTabTitle(String title)
{
tvTabTitle.setText(title); //my TextView that's needs to be changed.
Log.d(TAG, "set tab title from activity: "+title);
}
And that is it, this is how I changed a view of the activity depending on the visible fragment of the ViewPager.