MvxCachingFragmentStatePagerAdapter pass parameter to viewmodel - android

How can i pass parameter to my viewmodel when i build a List of Fragment for a viewpager ?
I try to use the "parametervaluesobject" in "MvxCachingFragmentStatePagerAdapter.FragmentInfo" but that doesn't seem to work.
[MvxFragment(typeof(MainViewModel), Resource.Id.content_frame, true)]
[Register("mvvmcrosslearning.droid.fragments.DateFragment")]
public class DateFragment : BaseFragment<DateViewModel>
{
protected override int FragmentId => Resource.Layout.fragment_date;
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var view = base.OnCreateView(inflater, container, savedInstanceState);
var viewPager = view.FindViewById<ViewPager>(Resource.Id.viewpager);
if (viewPager != null)
{
var fragments = new List<MvxCachingFragmentStatePagerAdapter.FragmentInfo>();
for (int i = 0; i < 3; i++)
fragments.Add(new MvxCachingFragmentStatePagerAdapter.FragmentInfo($"Date {i}",
typeof(RecyclerViewFragment), typeof(RecyclerViewModel), new Device() { Date = $"Date {i}" }));
viewPager.Adapter = new MvxCachingFragmentStatePagerAdapter(Activity,ChildFragmentManager,fragments);
viewPager.OffscreenPageLimit = 1;
}
var tabLayout = view.FindViewById<TabLayout>(Resource.Id.tabs);
tabLayout.SetupWithViewPager(viewPager);
return view;
}
}

Thanks you York Shen. I found how to get the data in my ViewModel :
Just override that method in the RecyclerViewModel's ViewModel:
protected override void InitFromBundle(IMvxBundle parameters)
{
base.InitFromBundle(parameters);
Device = new Device()
{
Date = parameters.Data["Date"]
};
RaisePropertyChanged(() => Device);
}

Related

Null when sharing data between Activity and Fragment

I got a problem that I can't share a RxBleClient between MainActivity and Fragments.
I pass a instance of RxBleClient to MyViewModel, and while trying to receive from ViewModel in Fragment it is just a Null. Fragment is a part of ViewPager2. Here is how I did this:
View Model code:
public class MyViewModel extends ViewModel {
private MutableLiveData<RxBleClient> rxBleClient = new MutableLiveData<RxBleClient>();
public MyViewModel() {
}
public void setRxBleClient(RxBleClient item) {
rxBleClient.setValue(item);
}
public LiveData<RxBleClient> getRxBleClient() {
return rxBleClient;
}
}
MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyViewModel model = new ViewModelProvider(this).get(MyViewModel.class);
// Turn on Bluetooth
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
int REQUEST_ENABLE_BT = 1;
this.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
// pass instance of RxBleClient to ViewModel
rxBleClient = RxBleClient.create(getApplicationContext());
model.setRxBleClient(rxBleClient);
// bind
ButterKnife.bind(this);
// rest of code
Fragment code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_connection_list, container, false);
scanResultList = new ArrayList<ScanResult>(0);
// Set the adapter
if (view instanceof RecyclerView) {
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view;
if (mColumnCount <= 1) {
recyclerView.setLayoutManager(new LinearLayoutManager(context));
} else {
recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
}
recyclerView.setAdapter(new MyConnectionRecyclerViewAdapter(scanResultList));
}
// get View Model
myViewModel = new ViewModelProvider(getActivity()).get(MyViewModel.class);
myViewModel.getRxBleClient().observe(getViewLifecycleOwner(), client -> {
this.rxBleClient = client; // HERE IS NULL
});
return view;
}
Where did I make mistake?
First edit:
This is my only one Activity, yet. This Activity is hosting ViewPager2:
// FRAGMENT ADAPTER
fragmentStateAdapter = new ViewPager2FragmentStateAdapter(getSupportFragmentManager(), getLifecycle());
viewPager2 = findViewById(R.id.pager);
viewPager2.setAdapter(fragmentStateAdapter);
// TOP BAR
final String tabTitles[] = {"Debugging", "Bluetooth", "Video"};
final #DrawableRes int tabDrawable[] = {R.drawable.ic_bug_report_24px, R.drawable.ic_bluetooth_24px, R.drawable.ic_videocam_24px};
tabLayout = findViewById(R.id.tab_layout);
new TabLayoutMediator(tabLayout, viewPager2,
(tab, position) -> tab.setText(tabTitles[position]).setIcon(tabDrawable[position])
).attach();

How to set few fragments that have same structure in viewpager?

I'm a beginner who learning Android basic course
I want to make 6 fragments that have same structure (only title, image, texts will be different) by using single fragment.
I tried this code but I can see only one fragment.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.fragment_container);
MoviePagerAdapter adapter = new MoviePagerAdapter(getSupportFragmentManager());
mainfragment = new MainFragment();
adapter.addItem(mainfragment);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(6);
}
ViewPager Adapter (in MainActivity)
class MoviePagerAdapter extends FragmentStatePagerAdapter {
public ArrayList<Fragment> items = new ArrayList<Fragment>();
#Override
public Fragment getItem(int position) {
return items.get(position);
}
public MoviePagerAdapter(#NonNull FragmentManager fm) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
public void addItem(Fragment item) {
items.add(item);
}
#Override
public int getCount() {
return items.size();
}
}
MainFragment.java
public class MainFragment extends androidx.fragment.app.Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.main_frargment, container,
false);
//...
'i want to make 6fragments with datas below '
movieData = new MovieData("title1", "rate1", "grade1");
addData(movieData);
movieData = new MovieData("title2", "rate2", "grade2");
addData(movieData);
movieData = new MovieData("title3", "rate3", "grade3");
addData(movieData);
movieData = new MovieData("title4", "rate4", "grade4");
addData(movieData);
movieData = new MovieData("title5", "rate5", "grade5");
addData(movieData);
movieData = new MovieData("title6", "rate6", "grade6");
addData(movieData);
return rootView;
}
public void addData(MovieData movieData){
Bundle bundle = new Bundle();
bundle.putParcelable("data", movieData);
MainFragment mainFragment = new MainFragment();
mainFragment.setArguments(bundle);
title.setText(movieData.title);
reservation_rate.setText(movieData.getReservation_rate());
grade.setText(movieData.getGrade());
image.setImageResource(R.drawable.image6);
}
}
change your code like this:
public class MainActivity extends AppCompatActivity {
private MoviePagerAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.fragment_container);
adapter = new MoviePagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(6);
for(int i =0;i<6;i++){
createFrag(i);
}
}
}
private void createFrag(int number) {
MainFragment fragment = new MainFragment();
Bundle args = new Bundle();
args.putInt("NUMBER",number);
fragment.setArguments(args);
adapter.addItem(fragment);
adapter.notifyDataSetChanged();
}
class MoviePagerAdapter extends FragmentStatePagerAdapter {
public ArrayList<Fragment> items = new ArrayList<Fragment>();
#Override
public Fragment getItem(int position) {
return items.get(position);
}
public MoviePagerAdapter(#NonNull FragmentManager fm) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
public void addItem(Fragment item) {
items.add(item);
}
#Override
public int getCount() {
return items.size();
}
}
and change your Fragment like this:
public class MainFragment extends androidx.fragment.app.Fragment {
//1st
private int number;
#Nullable
//this is variant 1 - with static Movie data
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable
ViewGroup container, #Nullable Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.main_frargment,
container,
false);
//...
//2d
assert getArguments() != null;
number = getArguments().getInt("NUMBER");
switch (number) {
case 0:
MmovieData movieData1 = new MovieData("title1", "rate1",
"grade1");
addData(movieData1);
break;
case 1:
MmovieData movieData2 = new MovieData("title2", "rate2",
"grade2");
addData(movieData2);
break;
//...
}
return rootView;
}
public void addData(MovieData movieData){
title.setText(movieData.title);
reservation_rate.setText(movieData.getReservation_rate());
grade.setText(movieData.getGrade());
image.setImageResource(R.drawable.image6);
}
}
and this is variant 2 ( with dynamic data and listener)
public class MainFragment extends androidx.fragment.app.Fragment {
//1st
private int number;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable
ViewGroup container, #Nullable Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.main_frargment,
container,
false);
//...
//2d
assert getArguments() != null;
number = getArguments().getInt("NUMBER");
return rootView;
}
//some method of listener changed
public void dataChanged(MovieData movieData, int position){
if(number==position){
title.setText(movieData.title);
reservation_rate.setText(movieData.getReservation_rate());
grade.setText(movieData.getGrade());
image.setImageResource(R.drawable.image6);
}
}

Switch to tab 2 after selecting ListView from tab 1

Here is a complete project: Google Drive.
Follow code:
Frag_Home_1_Tab.cs:
public class Frag_Home_1_Tab : Fragment
{
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
public static Frag_Home_1_Tab NewInstance()
{
return new Frag_Home_1_Tab { Arguments = new Bundle() };
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View inflate = inflater.Inflate(Resource.Layout.frag_tab1, container, false);
ListView mListView = inflate.FindViewById<ListView>(Resource.Id.listView);
ViewPager viewPager = inflate.FindViewById<ViewPager>(Resource.Id.viewPager);
mListView.ItemClick += (sender, e) =>
{
mListView.SetItemChecked(e.Position, true);
// ** Here, how to navigate to tab 2 and refresh gridview **
};
ArrayAdapter<string> adapter = new ArrayAdapter<string>(Activity, Android.Resource.Layout.SimpleListItemActivated1, List());
mListView.Adapter = adapter;
// Set the ChoiceMode
mListView.ChoiceMode = ChoiceMode.Single;
// Select default
mListView.SetItemChecked(0, true);
return inflate;
}
private List<string> List()
{
List<string> list = new List<string>
{
"List 1",
"List 2",
"List 3",
"List 4",
"List 5",
"List 6",
"List 7",
"List 8",
"List 9"
};
return list;
}
}
frag_tab1:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listView" />
</LinearLayout>
If you select from the "List5" list in tab 1, load 5 rows in the gridview of tab 2 and navigate to tab 2.
If you select from the "List9" list in tab 1, load 9 rows in the gridview of tab 2 and navigate to tab 2.
If you select from the "List2" list in tab 1, load 2 rows in the gridview of tab 2 and navigate to tab 2.
And so it goes ...
What I'm trying to say is: navigate to tab 2 when you click on tab button 1. Simple like that.
Any solution ?
Frag_Home_1:
public class Frag_Home_1 : Fragment
{
TabLayout tabLayout;
private static class SingletonHolder
{
public static Frag_Home_1 INSTANCE = new Frag_Home_1();
}
public static Frag_Home_1 getInstance()
{
return SingletonHolder.INSTANCE;
}
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View inflate = inflater.Inflate(Resource.Layout.frag_home_1, container, false);
ViewPager viewPager = inflate.FindViewById<ViewPager>(Resource.Id.viewPager);
MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(ChildFragmentManager);
viewPager.Adapter = adapter;
//TabLayout
tabLayout = inflate.FindViewById<TabLayout>(Resource.Id.sliding_tabs);
tabLayout.SetupWithViewPager(viewPager);
return inflate;
}
public void toTab2()
{
TabLayout.Tab tab = tabLayout.GetTabAt(1);
tab.Select();
}
public class MyFragmentPagerAdapter : FragmentPagerAdapter
{
public string[] titles = new string[] { "Tab1", "Tab2" };
List<Fragment> fgls = new List<Fragment>();
public MyFragmentPagerAdapter(FragmentManager fm) : base(fm)
{
fgls.Add(Frag_Home_1_Tab.NewInstance());
fgls.Add(Frag_Home_2_Tab.getInstance());
}
public override Fragment GetItem(int position)
{
return fgls[position];
}
public override ICharSequence GetPageTitleFormatted(int position)
{
return new String(titles[position]);
}
public override int Count
{
get { return titles.Length; }
}
}
}
Frag_Home_1_Tab's OnCreateView method:
mListView.ItemClick += (sender, e) =>
{
mListView.SetItemChecked(e.Position, true);
Frag_Home_1.getInstance().toTab2();
Frag_Home_2_Tab.getInstance().updateGrid(e.Position);
// ** Here, how to navigate to tab 2 and refresh gridview **
};
Frag_Home_2_Tab:
public class Frag_Home_2_Tab : Fragment,adapterUpdate
{
ArrayAdapter<string> adapter;
List<string> numbers = new List<string>();
GridView grid;
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
private static class SingletonHolder
{
public static Frag_Home_2_Tab INSTANCE = new Frag_Home_2_Tab();
}
public static Frag_Home_2_Tab getInstance()
{
return SingletonHolder.INSTANCE;
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
initData(9);
View view = inflater.Inflate(Resource.Layout.frag_tab2, container, false);
grid = (GridView)view.FindViewById(Resource.Id.gridview);
grid.ChoiceMode = ChoiceMode.Single;
grid.ItemClick += (sender, e) =>
{
grid.SetItemChecked(e.Position, true);
};
adapter = new ArrayAdapter<string>(Activity, Resource.Layout.item_tab_2, numbers);
grid.Adapter = adapter;
return view;
}
private void initData(int count)
{
numbers.Clear();
for (int i = 0; i < count; i++)
{
numbers.Add((i + 1).ToString());
}
}
public void updateGrid(int count)
{
initData(count+1);
adapter = new ArrayAdapter<string>(Activity, Resource.Layout.item_tab_2, numbers);
grid.Adapter = adapter;
}
}
public interface adapterUpdate
{
void updateGrid(int count);
}
In Frag_Home_1 and Frag_Home_2_Tab, I use single instance to avoid NullPointException.

Display layout in fragment on main activity xamarin

I am not able to display layout on class SecondFragment : Fragment
MAIN ACTIVITY
$ [Activity (Label = "project", Theme = "#style/Tab")]
public class TabActivity : Activity
{
ProductDB dbHelper;
ICursor cursor;
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.MainTab);
dbHelper = new ProductDB(this);
cursor = dbHelper.ReadableDatabase.RawQuery ("select * from movie", null);
StartManagingCursor (cursor);
this.ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;
AddTab ("Products", new FirstFragment(this, cursor));
AddTab ("User Profile", new SecondFragment());
AddTab("User Order", new ThirdFragment());
if (savedInstanceState != null)
this.ActionBar.SelectTab(this.ActionBar.GetTabAt(savedInstanceState.GetInt("tab")));
}
void AddTab (string tabText, Fragment view)
{
var tab = this.ActionBar.NewTab ();
tab.SetText (tabText);
tab.TabSelected += delegate(object sender, ActionBar.TabEventArgs ab)
{
var fragment = this.FragmentManager.FindFragmentById(Resource.Id.frameLayout1);
if (fragment != null)
ab.FragmentTransaction.Remove(fragment);
ab.FragmentTransaction.Add (Resource.Id.frameLayout1, view); };
tab.TabUnselected += delegate(object sender, ActionBar.TabEventArgs ab) {
ab.FragmentTransaction.Remove(view); };
this.ActionBar.AddTab (tab);
}
protected override void OnDestroy ()
{
StopManagingCursor (cursor);
cursor.Close ();
base.OnDestroy ();
}
class FirstFragment: Fragment
{
ICursor cursor;
ListView listView;
Activity context;
public FirstFragment(Activity context, ICursor cursor) {
this.cursor = cursor;
this.context = context;
}
public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView (inflater, container, savedInstanceState);
var view = inflater.Inflate (Resource.Layout.Tab1, container, false);
listView = view.FindViewById<ListView> (Resource.Id.mylist);
listView.Adapter = new ProductAdapter (context, cursor);
listView.ItemClick += OnItemListClick;
return view;
}
protected void OnItemListClick (object sender, AdapterView.ItemClickEventArgs ab)
{
var curs = (ICursor)listView.Adapter.GetItem (ab.Position);
var movieName = curs.GetString (1);
Android.Widget.Toast.MakeText (context, movieName, Android.Widget.ToastLength.Short).Show();
}
}
class SecondFragment : Fragment
{
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.Inflate(R.layout.your_fragment, container, false);
return view;
}
// Inflate the layout for this fragment
// return inflater.inflate(R.layout.article_view, container, false);
// base.OnCreateView(inflater, container, savedInstanceState);
// var view = inflater.Inflate(Resource.Layout.User, container, false);
// var layout = view.FindViewById<LinearLayout>(Resource.Id.linearLayoutmargin1);
// return view;
}
class ThirdFragment : Fragment
After observing above code, there might be some issue in onCreateView of SecondFragment, you missed below line,
base.OnCreateView (inflater, container, savedInstanceState);
Confirm and let me know whether working or not?
:)GlbMP

Import text from fragmentactivity to fragment

I want to create a common search for different websites at same time.So I imported text of an EditText from an activity to Fragment activity.Now how to import that text to a fragment?
FragmentActivity:
public class MyActivity6 extends FragmentActivity {
TextView mTextview;
ViewPager viewPager = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_activity6);
viewPager = (ViewPager) findViewById(R.id.pager);
FragmentManager fragmentManager = getSupportFragmentManager();
viewPager.setAdapter(new MyAdapter(fragmentManager));
mTextview = (TextView)findViewById(R.id.textView8);
mTextview.setText(getIntent().getStringExtra("mytext"));
}
class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
Fragment fragment = null;
if (i == 0) {
fragment = new FragmentA();
}
if (i == 1) {
fragment = new FragmentB();
}
if (i == 2) {
fragment = new FragmentC();
}
if (i == 3) {
fragment = new FragmentD();
}
return fragment;
}
#Override
public int getCount() {
return 4;
}
public CharSequence getPageTitle(int position) {
String title = new String();
if (position == 0) {
return "Flipkart";
}
if (position == 1) {
return "Amazon";
}
if (position == 2) {
return "Snapdeal";
}
if (position == 3) {
return "Ebay";
}
return null;
}
}
Fragment :
`
public class FragmentA extends Fragment {
TextView mText;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View mainView = (View)
inflater.inflate(R.layout.fragment1, container, false);
WebView webView = (WebView)
mainView.findViewById(R.id.webView12);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.getAllowContentAccess();
webSettings.getDatabaseEnabled();
webSettings.getAllowFileAccess();
webSettings.getCacheMode();
webView.loadUrl("http://m.flipkart.com/search?q=");
webView.setWebViewClient(new WebViewClient());
// Set up the ViewPager with the sections adapter.
webView.setWebViewClient(new MyWebViewClient());
return mainView;}
}
Rather than use the default constructor for your Fragment, follow this common pattern of using a static newInstance() method to pass arguments. Stash these into the arguments bundle then pull them out in the Fragment during its onCreateView() (or wherever you actually need it.)
public class MyFragment extends Fragment {
...
private static final String ARG_TEXT = "_arg_text";
...
public static MyFragment newInstance(String myText) {
Bundle args = new Bundle();
args.putString(ARG_TEXT, myText);
MyFragment ret = new MyFragment();
ret.setArguments(args);
return;
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View mainView = (View)
inflater.inflate(R.layout.fragment1, container, false);
Bundle args = getArguments();
String text = args.getString(ARG_TEXT);
// Now use the text however you'd lik
...
}
}

Categories

Resources