so I'm working on an app that utilizes a fixed 2 tabs within a view pager. I have a RecyclerView inside of a ViewPager but the RecyclerView is not responding to horizontal swipes. I have disabled swiping to change pages within the ViewPager by overriding onInterceptTouchEvent and onTouchEvent. I've called setFocusable(false) and setFocusableInTouchMode(false) on the view pager to no avail. Any ideas?
// ViewPager code
pager = (NoSwipePager) findViewById(R.id.pager);
pager.setFocusable(false);
pager.setFocusableInTouchMode(false);
adapter = new FormTabAdapter(getSupportFragmentManager(), form, editing);
pager.setAdapter(adapter);
pager.setCurrentItem(0);
tabs = (PagerTabStrip) findViewById(R.id.tab_strip);
tabs.setTabIndicatorColor(Color.WHITE);
tabs.setBackgroundColor(Color.parseColor("#A52A2A"));
tabs.setTextColor(Color.WHITE);
// RecyclerView code
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(act);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
rv.setLayoutManager(linearLayoutManager);
((SimpleItemAnimator) rv.getItemAnimator()).setSupportsChangeAnimations(false);
elementsAdapter = new ElementsAdapter(listener, act, new LinkedList<>(elements), editing);
rv.setAdapter(elementsAdapter);
ItemTouchHelper.Callback callback = new ElementTouchHelper(elementsAdapter);
ItemTouchHelper helper = new ItemTouchHelper(callback);
helper.attachToRecyclerView(rv);
For that you need to off viewpager swaping both are not working at same time.
Too disable swip of viewpager use below code
public class MyViewPager extends ViewPager {
private boolean enabled;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = true; // default swipe enable is true
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
// true - enable swipe
// false - disable swipe
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
and use below code while using viewpager in .xml file
<package.MyViewPager
android:id="#+id/viewPager"
android:layout_height="match_parent"
android:layout_width="match_parent" />
Hope these answer helps you.
These same approach you can use use it for recyclerview also if you required in future.
Hope these help you.
You can use fragment to show RecycleView.
For example:
You will create a class Adapter to manage.
public class HomeFragmentAdapter extends FragmentPagerAdapter {
private final ArrayList<Fragment> mFragment = new ArrayList<>();
private final ArrayList<String> mFragmentTitle = new ArrayList<>();
public HomeFragmentAdapter(FragmentManager fragmentManager){
super(fragmentManager);
}
public void addFragment(Fragment fragment, String title){
mFragment.add(fragment);
mFragmentTitle.add(title);
}
#Override
public Fragment getItem(int position) {
return mFragment.get(position);
}
#Override
public int getCount() {
return mFragment.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitle.get(position);
}
}
And after that you will add more fragment which include any RecycleView you need.
public class HomeFragment extends Fragment {
public static TabLayout tabLayout;
public static ViewPager viewPager;
Menu mMenu;
public HomeFragment(){
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
setHasOptionsMenu(true);
View view = inflater.inflate(R.layout.fragment_layout_home, null);
tabLayout = (TabLayout) view.findViewById(R.id.tab_home);
viewPager = (ViewPager) view.findViewById(R.id.viewpager_home);
if(viewPager != null){
setupViewPager(viewPager);
}
tabLayout.setTabMode(TabLayout.MODE_FIXED);
tabLayout.setupWithViewPager(viewPager);
return view;
}
private void setupViewPager(ViewPager viewPager){
HomeFragmentAdapter adapter = new HomeFragmentAdapter(getChildFragmentManager());
adapter.addFragment(new ExpenseFragment(), "Expense");
adapter.addFragment(new IncomeFragment(), "Income");
viewPager.setAdapter(adapter);
}
T hope it could been help you.
Related
I am relatively new to writing apps and I am currently working at my second project. I have an activity called AddNetwork, which contains a button that should open an AlertDialog. In the AlertDialog I want to have a TabLayout with two tabs, that each show different content. I have been trying to achieve this for about 8 hours and I have found a few tutorials that partially cover my problem, but nothing that is really on point. I think I could solve my problem using ViewPager2, but I haven't managed to get it working yet. As of now my code works as follows:
AddNetwork.java creates an instance of AlertDialogSelectWifi.java, which extends DialogFragment and inflates the alertdialog_select_wifi.XML layout file that contains a TabLayoutand a ViewPager2. Also in the DialogFragment, I am trying to set an adapter to the viewPager, namely ViewPagerAdapter.java, which extends FragmentStateAdapter. From there I would want to attach the two fragments AlertDialogRecentFragment.java (with fragment_alert_dialog_recent.xml) and AlertDialogTypeFragment.java (with fragment_alert_dialog_type.xml). Note that the latter is not yet included in the code, so as of now I would only add one fragment to the tabs (I guess).
So at the moment, my code is a somewhat chaotic mixture of all the tutorials I found and followed. It does not cause any errors and I am able to open the Alertdialog, however, the fragment_alert_dialog_recent.xml and the tabs are not visible.
I really don't know what else I could try or change in my code. Overall I am not sure whether it is correct to set the ViewPagerAdapter in the AlertDialogSelectWifi.java file or not. What am I missing or doing wrong? Any help is grealty appreciated!
Here is my code:
AddNetwork.java
public class AddNetwork extends AppCompatActivity {
Context context = this;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_network);
//BUTTON
final MaterialButton buttonSelectWifi;
buttonSelectWifi = (MaterialButton) findViewById(R.id.button2);
buttonSelectWifi.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//CREATE ALERT DIALOG
FragmentManager fm = getSupportFragmentManager();
DialogFragment dialog = AlertDialogSelectWifi.newInstance(context);
dialog.show(fm, "dialog");
}
});
}
}
AlertDialogSelectWifi.java
public class AlertDialogSelectWifi extends DialogFragment {
static Context mContext;
public static AlertDialogSelectWifi newInstance(Context context) {
mContext = context;
return new AlertDialogSelectWifi();
}
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme);
LayoutInflater inflater = requireActivity().getLayoutInflater(); //getActivity().getLayoutInflater();
View alertLayout = inflater.inflate(R.layout.alertdialog_select_wifi, null);
builder.setTitle("Add Saved Network")
.setView(alertLayout)
.setCancelable(true)
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
return builder.create();
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.alertdialog_select_wifi, container, false);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ViewPager2 viewPager = view.findViewById(R.id.viewpager);
TabLayout tabLayout = view.findViewById(R.id.tablayout);
ViewPagerAdapter adapter = new ViewPagerAdapter(getActivity(), mContext, viewPager);
viewPager.setAdapter(adapter);
new TabLayoutMediator(tabLayout, viewPager,
new TabLayoutMediator.TabConfigurationStrategy() {
#Override
public void onConfigureTab(#NonNull TabLayout.Tab tab, int position) {
tab.setText("Tab " + (position + 1));
}
}).attach();
}
}
ViewPageAdapter.java
public class ViewPagerAdapter extends FragmentStateAdapter {
private LayoutInflater mInflater;
private ViewPager2 viewPager;
public ViewPagerAdapter(FragmentActivity fragmentActivity, Context context, ViewPager2 viewPager) {
super(fragmentActivity);
this.mInflater = LayoutInflater.from(context);
this.viewPager = viewPager;
}
#NonNull
#Override
public Fragment createFragment(int position) {
return AlertDialogRecentFragment.newInstance();
}
#Override
public int getItemCount() {
return 0;
}
}
if i understood your problem correctly change your adapter like this:
public class ViewPagerAdapter extends FragmentStateAdapter {
public ViewPagerAdapter(FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
#NonNull
#Override
public Fragment createFragment(int position) {
if(position == 0)
return new AlertDialogRecentFragment();
else
return new AlertDialogTypeFragment();
}
#Override
public int getItemCount() {
return 2;
}
}
I have an Weather adapter to show the weather, the activity is split into two screens, one half a listview (different adapter), the other is tablayout with another tablayout inside to scroll through all the different pages of weather that are available
After turning off the wifi to make sure i don't receive anything and then turning on the wifi to receive the weather i get the update method called for the adapter and the list is updated, new fragments created, onViewCreated is called but the fragments display as blank and as only 1 (can't cycle through them if there are multiple).
Here is the Weather ViewPagerAdapter
public class WeatherViewPagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> fragments;
public WeatherViewPagerAdapter(FragmentManager fm) {
super(fm);
fragments = new LinkedList<>();
if (Storage.getInstance().getWeatherModels().size() == 0){
// Displays page but with "no weather available" message
fragments.add(WeatherFragment.newInstance(null));
}else{
for (CurrentWeatherModel model : Storage.getInstance().getWeatherModels()){
fragments.add(WeatherFragment.newInstance(model));
}
}
}
public void rediscoverWeather(){
fragments.clear();
if (Storage.getInstance().getWeatherModels().size() == 0){
fragments.add(WeatherFragment.newInstance(null));
}else{
for (CurrentWeatherModel model : Storage.getInstance().getWeatherModels()){
fragments.add(WeatherFragment.newInstance(model));
}
}
}
#Override
public int getItemPosition(#NonNull Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public Parcelable saveState() {
return null;
}
}
And this is the fragment that is in the Tablayout on the side that displays the weather
public class WeatherViewPagerFragment extends Fragment {
private WeatherViewPagerAdapter adapter;
private ViewPager viewpager;
private TabLayout tabLayout;
public static WeatherViewPagerFragment newInstance(){
return new WeatherViewPagerFragment();
}
#Override
public UniqueInfo getUniqueInfo() {
return null;
}
#Override
public void update() {
adapter.rediscoverWeather();
setPage(0);
adapter.notifyDataSetChanged();
}
public void setPage(int pageNumber){
if (pageNumber >=0 && pageNumber < adapter.getCount()){
viewpager.setCurrentItem(pageNumber, true);
}
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.weather_view_pager, container, false);
}
private void createAdapter(){
adapter = new WeatherViewPagerAdapter(getChildFragmentManager());
viewpager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewpager);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewpager = view.findViewById(R.id.viewpager);
tabLayout = view.findViewById(R.id.sliding_tabs);
createAdapter();
}
}
The update() for WeatherViewPagerFragment gets called when its meant to, which updates the Adapter, re-doing the fragments and calling onCreateView and onViewCreated, but what i see is just a blank fragment, any suggestions why this would be happening? i figured it could be a focus issue but i haven't had any luck as of yet with fixing it
I have simple problem.. I have MainActivity.. inside it i have 5 fragments and i can move using bottom navigation bar without problem!
In first fragment (Profile) i have inside that tow fragment using Tablayout and Viewpager..
First Fragment (Friends) Second Fragment (Users)..
My problem when i run app and open (Profile) the tow fragments (Friends and Users)
Working 100% just in first time.. when i come back to other fragment using bottom bar and come back to friends or users is empty and not load !
I want attach some of my codes you will need it..
Profile Fragment:
mSectionsPageAdapter = new
SectionsPageAdapter(getActivity().getSupportFragmentManager());
mViewPager = (ViewPager) v.findViewById(R.id.container);
setupViewPager(mViewPager);
TabLayout tabLayout = (TabLayout) v.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
mSectionsPageAdapter.notifyDataSetChanged();
private void setupViewPager(ViewPager viewPager) {
SectionsPageAdapter adapter = new
SectionsPageAdapter(getActivity().getSupportFragmentManager());
adapter.addFragment(new FriendsFragment(), "Friends");
adapter.addFragment(new UsersFragment(), "Online");
viewPager.setAdapter(adapter);
}
SectionsPageAdapter:
public class SectionsPageAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
public SectionsPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}}
I try to add this in Friends Fragment and Users Fragment the problem was solved but the content duplicated in first time run only.
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
getFragmentManager().beginTransaction().detach(this).attach(this).commit();
}
}
SectionsPageAdapter:
public class SectionsPageAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
public SectionsPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}}
A possible reason for your problems could be you are mixing up FragmentManagers.
In your Activity to handle the bottom navigation you should use Activity#getSupportFragmentManager().
But for any of the Fragments inside that activity, if you want to have children/nested fragments. You should use Fragment#getChildFragmentManager().
So in your profile fragment, while populating the two tabs pager, you should pass it Fragment#getChildFragmentManager() instead of getActivity().getSupportFragmentManager()
You can use interface to solve this problem. Implement interface in your "User" & "Friend" fragments & call the interface method when your "Profile" fragments "OnCreateView" is called. You can load data when interface method is called. For reference, Please check this link:
Communicating with Other Fragments
EDIT
Sorry,you can load data without using Interface. Here is some sample code:
Profile Fragment:
ProfileFragment extends Activity {
FriendsFragment friends;
UsersFragment users;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mSectionsPageAdapter = new
SectionsPageAdapter(getActivity().getSupportFragmentManager());
mViewPager = (ViewPager) v.findViewById(R.id.container);
setupViewPager(mViewPager);
TabLayout tabLayout = (TabLayout) v.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
mSectionsPageAdapter.notifyDataSetChanged();
friends.update();
users.update();
}
private void setupViewPager(ViewPager viewPager) {
SectionsPageAdapter adapter = new
SectionsPageAdapter(getActivity().getSupportFragmentManager());
friends = new FriendsFragment();
users = new UsersFragment();
adapter.addFragment(friends, "Friends");
adapter.addFragment(users, "Online");
viewPager.setAdapter(adapter);
}
Friends Fragment:
FriendFragment extends Activity {
public void update(){
// load data
}
jest Use
ViewPagerAdapter(getChildFragmentManager())
getChildFragmentManager()
I have got classic Bottom Navigation created by default with 3 TABs (FragmentOne, FragmentTwo and FragmentThree).
The first fragment (FragmentOne) has ViewPager with two static inner Fragments (FragmentInner1 and FragmentInner2).
When app starts evrything is fine so at the FragmentOne we can see FragmentInner1 and can navigate to FragmentInner2.
But after navigating from FragmentTwo to FragmentOne the FragmentInner1 is not visible. That is a problem.
I guess we should recreate it somehow?
I investigated manual from here https://developer.android.com/guide/components/fragments.html and https://developer.android.com/training/implementing-navigation/lateral.html#PagerTitleStrip but it does not help and my code looks the same way.
Please help. Thank you!
FragmentOne
public class FragmentOne extends Fragment {
//This is our viewPager
private ViewPager viewPager;
//Fragments
FragmentInner1 fragmentInner1;
FragmentInner2 fragmentInner2;
ViewPagerAdapter adapter;
private View view;
public FragmentOne() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_fragment_one, container, false);
//Initializing viewPager
viewPager = (ViewPager) view.findViewById(R.id.viewpager);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
setupViewPager(viewPager);
return view;
}
private void setupViewPager(ViewPager viewPager) {
adapter = new ViewPagerAdapter(getActivity().getSupportFragmentManager());
fragmentInner1=new FragmentInner1();
fragmentInner2=new FragmentInner2();
adapter.addFragment(fragmentInner1);
adapter.addFragment(fragmentInner2);
viewPager.setAdapter(adapter);
}
#Override
public void onAttach(Context context)
{
super.onAttach(context);
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
ViewPagerAdapter
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
Fragment fragment = mFragmentList.get(position);
return fragment;
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment) {
mFragmentList.add(fragment);
}
}
FragmentInner1
public class FragmentInner1 extends Fragment {
public static FragmentInner1 newInstance( ) {
FragmentInner1 fragment = new FragmentInner1();
return fragment;
}
public FragmentInner1() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_fragment_inner1, container, false);
}
}
You have to Use getChildFragmentManager() For Viewpager to adapt Popback Feature.
adapter = new ViewPagerAdapter(getChildFragmentManager());
This is Because the Viewpager have multiple Fragments where Viewpager itself or is holded by another Fragment. So the Child Fragment is to Be Invoked and Used.
You Can Refer this Documentation on ChildFragmentManager()
I wanted to use recyclerview inside a fragment of my 3 fragment viewpager. I wrote the code and it ran perfectly but I don't know why it is too slow.When I swap from one fragment to another it almost takes half minute.Don't know what mistakes I did here.
Main Activity
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar)findViewById(R.id.toolBar);
tabLayout = (TabLayout)findViewById(R.id.tabs);
viewPager = (ViewPager)findViewById(R.id.viewPager);
setSupportActionBar(toolbar);
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPagerAdapter.addFragment(new OneFragment(), "One");
viewPagerAdapter.addFragment(new TwoFragment(), "Two");
viewPagerAdapter.addFragment(new ThreeFragment(), "Three");
viewPager.setAdapter(viewPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
}
}
Here it is one of my fragment where I tried to implement recyclerview.
Fragment
public class TwoFragment extends Fragment {
public TwoFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_two, container, false);
OurData ourData = new OurData();
ourData.pic.add(R.drawable.b);
ourData.title.add("Hello");
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.listRecyclerView);
ListAdapter listAdapter = new ListAdapter();
recyclerView.setAdapter((listAdapter));
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
return view;
}
}
public class ListAdapter extends RecyclerView.Adapter {
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new ListViewHolder(view);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((ListViewHolder) holder).bindView(position);
}
#Override
public int getItemCount() {
return OurData.title.size();
}
private class ListViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView text;
private ImageView image;
public ListViewHolder(View itemview) {
super(itemview);
text = (TextView) itemview.findViewById(R.id.textF);
image = (ImageView) itemview.findViewById(R.id.imageF);
itemview.setOnClickListener(this);
}
public void bindView(int position) {
text.setText(OurData.title.get(position));
image.setImageResource(OurData.pic.get(position));
}
public void onClick(View view) {
}
}
}
public class OurData {
public static ArrayList<String> title = new ArrayList<String>();
public static ArrayList<Integer> pic = new ArrayList<Integer>();
}
It tooks my whole day thinking what I did wrong. Please help me out!
set your adapter recyclerView.setAdapter((listAdapter));
insise onViewCreated instead of onCreateView
I think the problem is because of one of your Methods.
maybe 'OurData'
and also are you sure of this:
#Override
public int getItemCount() {
return OurData.title.size();
}
also try using Log in each code and see the part that takes time especially 'OurData'