Android TabLayout prevent activation of tabs adjacent to selected
I have a tab-based app. I am using A TabLayout for my tabs and a subclass of FragmentStatePagerAdapter to instantiate the fragment for the selected tab. I have disabled swiping between tabs. I am still seeing a callback to create a fragment for tabs adjacent to the selected tab. In other words, if the tab at index 0 is activated, I also see a callback to GetItem for the tab at index 1.
I want to disable that behaviour. In other words, it should only request a fragment for the active tab. Is that possible?
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/root">
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabPaddingStart="0dp"
app:tabPaddingEnd="0dp"
app:tabPaddingTop="0dp"
app:tabMode="fixed"
app:tabGravity="fill" />
<jockusch.calculator.droid.AndroidViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
2 answers
-
answered 2018-07-12 01:09
RoyalGriffin
viewPager.setOffscreenPageLimit(0)
is what you are looking for. But a ViewPager doesn't allow offscreen limit less than 1.
Use something else than a viewPager to get your desired effect. One way of doing it without viewPager would be to have a frameLayout instead and inflate a new fragment and destroy the previous one when a tab is selected.
-
answered 2018-07-12 01:12
Jackey
The reason this is happening is due to you using a ViewPager.
ViewPager, by default, will auto-create the adjacent Fragments because this allows the user to swipe to them whenever they wish. Creating them only when they're ready to swipe might cause lag or some unpleasant visual effects.
ViewPager has a method called
setOffscreenPageLimit(int limit)
which can limit the amount of adjacent it keeps in memory, however I believe it's not possible to decrease it to 0 due to ViewPager's innate behavior.If you've already disabled swiping between tabs, then it sounds like what you want isn't a ViewPager. Consider just using FragmentTransactions to replace the active Fragment.
See also questions close to this topic
-
How to build the jar file from android studio project including classes,resources and jnilibs
I have created the module in android studio i want to make that module as a jar including classes,resources, jni libs.
-
Parsing iterative json objects using retrofit/gson
I'm being sent something like the following from a server I'm required to connect to:
{ "properties": { "prop1": { "type": "string", "title": "string" }, "prop2": { "type": "string", "title": "string" }, "prop3": { "type": "string", "title": "string" }, "prop4": { "type": "string", "title": "string" } } }
Obviously it would be more ideal for the server to send an array of objects with an id field, but I can't change it unfortunately. The numbers after "prop" can go up ad infinitum (though realistically won't go above 50 or so), is there a graceful way to handle this in Retrofit 2/GSON? or do I need to intercept this call and do it manually each time?
In a perfect world I'd like to end up with an array of "Prop" pojos that have an id field (1, 2, 3, etc), or even with "prop1", "prop2" etc in a field in each object.
-
How to localize app name shown in launcher using flutter?
how to localize app name shown in launcher? For example, "Play Store", in Chinese is "Play 商店". Thanks.
I tried to modeify android\app\src\main\AndroidManifest.xml
android:label="@string/app_name"
And create files
values-zh/strings.xml values-en/string.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">App name in different language</string> </resources>
Buuuuuuuuuuuuuuuut! The app name changes only when the system language changed. Is this a common problem(bug) in Android?
In windows, when the app language changes, the app name will change immediately.
So, what I really want is, when change the languages in my app, the app name in the launcher will also change, ignoring the system language.
-
testDefaultGrantsWithRemoteExceptions in Xamarin.Android
Recently I have implemented firebase in my Xamarin Android project. After that it is working successfully in Debug mode,but when i go to release mode, application is getting installed but crashes on opening. I saw the Device log,saw some error saying-
testDefaultGrantsWithRemoteExceptions:android.content.pm.PackageManager$NameNotFoundException: com.google.android.permission.gts
I am not sure whether it is related to firebase or something else. Just visited the link- https://sunj.iteye.com/blog/2387714
How can i do this in Xamarin.Android where this method can be implemented, also how will it effect application.
Also is there any way to see the reason why application is crashing,there is no error ,no exception.In output window also nothing weird showing,but still crashes in Release mode.
Thanks,
-
Xamarin.Forms Gesture Recognizer - The event 'View.GenericMotion' can only appear on the left hand side of += or -=
I have been working through many of the answers to the question about events and how they require a backing delegate field that will be used to store added callbacks. However, I am still extremely confused how that applies to the way I am implementing it. Below is the exact answer that I tried to follow and implement based on the question and answer, but to no avail.
https://stackoverflow.com/a/41641881/8065149
Overall, I am attempting to add custom gestures to a custom map render in Xamarin and Android. I want to be able to, on tap and hold, add a pin to my map. I have currently figured out how to add pins through a tap, but I want to change it to a long tap. Below is the tutorial that I have used to try to add gestures to my project, as it looked promising (even though his website isn't secure). And below the website is the github project as well in case that is easier to follow.
https://arteksoftware.com/gesture-recognizers-with-xamarin-forms/ https://github.com/RobGibbens/XamarinFormsGestureRecognizers
Below is the code in question. Specifically, the two lines
if (this.GenericMotion != null)
andif (this.Touch != null)
. Both of those lines throw the error:The event 'View.GenericMotion' can only appear on the left hand side of += or -=
.protected override void OnElementChanged (ElementChangedEventArgs<Label> e) { base.OnElementChanged (e); if (e.NewElement == null) { if (this.GenericMotion != null) { this.GenericMotion -= HandleGenericMotion; } if (this.Touch != null) { this.Touch -= HandleTouch; } } if (e.OldElement == null) { this.GenericMotion += HandleGenericMotion; this.Touch += HandleTouch; } } void HandleTouch(object sender, TouchEventArgs e) { _detector.OnTouchEvent(e.Event); } void HandleGenericMotion(object sender, GenericMotionEventArgs e) { _detector.OnTouchEvent(e.Event); }
I attempted to follow the answer that I posted earlier, but I was confused about how I was supposed to check whether they were null or not, and then if they were how I as supposed to call the handlers that will actually work with the touch events.
If more code is required to shed some light on the problem please post a comment. Thank you.
-
my activity_main.axml in visual studio 2017 xamarin android app don't have any layout design showed
Hello and good day developers, i am here again to ask you some question related to my new build project in visual studio 2017 xamarin android app.used blank app..the issue is i can't see my layout design, also when i drag and drop a button, textbox etc, but when i click the center of the white background there is a rectangular blueprint show or blue border..Note: this is a built in code.
// activity_main.axml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> </RelativeLayout>
// MainActivity.cs
using Android.App; using Android.OS; using Android.Support.V7.App; using Android.Runtime; using Android.Widget; namespace MhylesOrdering { [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] public class MainActivity : AppCompatActivity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // Set our view from the "main" layout resource SetContentView(Resource.Layout.activity_main); } } }
-
Navigation Drawer seems to be over the tablayout
I'm a creating a app with navigation Drawer and TabLayout. I created the navigation Drawer and added the TabLayout, each tab is supossed to have a fragmente, but the fragment isn't appearing, it's like the Draweaver is "covering" them. Does someone knows what's my mistake here?
Home activitiy
public class Home extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { FirebaseAuth mAuth; FirebaseUser currentUser ; private TabLayout tabLayout; private PagerAdapter adapter; private ViewPager viewPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); //TabLayout tabLayout =(TabLayout) findViewById(R.id.tablayout_id); viewPager =(ViewPager) findViewById(R.id.viewpager_id); adapter = new PageAdapter(getSupportFragmentManager()); //Add fragment ((PageAdapter) adapter).AddFragment(new AnuncioFragmento(),"Anuncio"); ((PageAdapter) adapter).AddFragment(new PedidoFragmento(),"Pedido"); viewPager.setAdapter(adapter); tabLayout.setupWithViewPager(viewPager); mAuth = FirebaseAuth.getInstance(); currentUser = mAuth.getCurrentUser(); //MenuView DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawer.addDrawerListener(toggle); toggle.syncState(); NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); navigationView.setNavigationItemSelectedListener(this); updateNavHeader(); }); } @Override public void onBackPressed() { DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); if (drawer.isDrawerOpen(GravityCompat.START)) { drawer.closeDrawer(GravityCompat.START); } else { super.onBackPressed(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.home, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } @SuppressWarnings("StatementWithEmptyBody") @Override public boolean onNavigationItemSelected(MenuItem item) { // Handle navigation view item clicks here. int id = item.getItemId(); if (id == R.id.nav_camera) { // Handle the camera action } else if (id == R.id.nav_gallery) { } else if (id == R.id.nav_slideshow) { } else if (id == R.id.nav_manage) { } else if (id == R.id.nav_share) { } else if (id == R.id.nav_logout) { } DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); return true; }
XML
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start"> <include layout="@layout/app_bar_home" android:layout_width="match_parent" android:layout_height="match_parent" /> <android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header_home" app:menu="@menu/activity_home_drawer" /> </android.support.v4.widget.DrawerLayout>
The fragments are added on this XML that are the app_bar_home
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".Atividades.Home"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay"/> <android.support.design.widget.TabLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" app:tabMode="fixed" app:tabGravity="fill" app:tabIndicatorColor="@color/colorAccent" android:id="@+id/tablayout_id"></android.support.design.widget.TabLayout> <android.support.v4.view.ViewPager android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/viewpager_id"></android.support.v4.view.ViewPager> </android.support.design.widget.AppBarLayout> <com.getbase.floatingactionbutton.FloatingActionsMenu android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginLeft="290dp" > <com.getbase.floatingactionbutton.FloatingActionButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/colorPrimary" app:fab_icon="@drawable/ic_add_blue" app:fab_size="mini" android:id="@+id/add_anuncio" app:fab_title="Anúncio" /> <com.getbase.floatingactionbutton.FloatingActionButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/colorPrimary" app:fab_icon="@drawable/ic_add_blue" app:fab_size="mini" android:id="@+id/add_pedido" app:fab_title="Pedido" /> </com.getbase.floatingactionbutton.FloatingActionsMenu> <include layout="@layout/content_home" /> </android.support.design.widget.CoordinatorLayout>
I said it's covering the fragments and the tab, because the tabs don't slide and i changed the coolor of the fragments and it isnt showing on the app. After that i changed the Collor of the Drawlayout XML and it's showing.
Please what did i do wrong?
Edit PageAdapter
public class PageAdapter extends FragmentPagerAdapter { private final List<Fragment> listfragment = new ArrayList<>(); private final List<String> listTitle = new ArrayList<>(); public PageAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return listfragment.get(position); } @Override public int getCount() { return listTitle.size(); } @Override public CharSequence getPageTitle(int position) { return listTitle.get(position); } public void AddFragment (Fragment fragment, String title ) { listfragment.add(fragment); listTitle.add(title); }
Fragmento 1
public class AnuncioFragmento extends Fragment { View v; public AnuncioFragmento() { } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { v = inflater.inflate(R.layout.anuncio_fragment, container, false); return v;
XML
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorPrimary"> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/anuncio_reciclerview"> </android.support.v7.widget.RecyclerView> </android.support.constraint.ConstraintLayout>
fragmento 2
public class PedidoFragmento extends Fragment { View v; public PedidoFragmento() { } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { v = inflater.inflate(R.layout.pedido_fragmento, container, false); return v;
XML
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/pedido_recyclerview" android:layout_marginBottom="20dp"> </android.support.v7.widget.RecyclerView> </android.support.design.widget.CoordinatorLayout>
-
Android - Unexpected OnTabReselected call
I am using
TabLayout
in conjunction with FragNav by ncapdevi. I have 4 tabs in theTabLayout
withTab A
as the initial tab.This is how I initialize my tabs
private void initTab() { if (bottomTabLayout != null) { for (int i = 0; i < TABS.length; i++) { bottomTabLayout.addTab(bottomTabLayout.newTab()); TabLayout.Tab tab = bottomTabLayout.getTabAt(i); if (tab != null) tab.setCustomView(getTabView(i)); } } } private View getTabView(int position) { View view = LayoutInflater.from(this).inflate(R.layout.home_item_bottom, new ConstraintLayout(this)); AppCompatImageView icon = view.findViewById(R.id.home_item_bottom_icon); CustomFontTextView name = view.findViewById(R.id.home_item_bottom_name); icon.setImageDrawable(ContextCompat.getDrawable(this, mTabIconsSelected[position])); name.setText(TABS[position]); return view; }
I use
addOnTabSelectedListener
for myTabLayout
and it works as expected on first press on any Tab.Here's the chronological order :
Press tab B,
OnTabSelectedListener
calledPress back, I return to A
Press tab B again,
OnTabReselectedListener
called
I don't expect this to happen as it isn't the same tab (Pressing B from A, but it acts as if I reselected the same tab).
Is there anything wrong with my code? If there's any code needed from my app which is crucial to help fixing this problem, just tell me and I will post it here :)
- Android select next tab automatically and load their Items accordingly in single list