Android Tabview + Webview - java

I want to make the webview content change (url change) when tab is changed.
However, my code is late. When I change tabs, it shows the last tab's content.
For example,
App Initialize -> shows first tab and first tab's webview (success)
Click Tab 2 -> shows second tab but first tab's webview (fail)
Click Tab 3 -> shows third tab but first tab's webview (fail)
Return to Tab 2 -> shows second tab and second tab's webview (success)
Please help.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
final ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
tabs.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
}
SectionsPagerAdapter.java
/**
* A [FragmentPagerAdapter] that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
#StringRes
private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2, R.string.tab_text_3, R.string.tab_text_4, R.string.tab_text_5, R.string.tab_text_6, R.string.tab_text_7};
private final Context mContext;
public SectionsPagerAdapter(Context context, FragmentManager fm) {
super(fm);
mContext = context;
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1);
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return mContext.getResources().getString(TAB_TITLES[position]);
}
#Override
public int getCount() {
// Show 2 total pages.
return 7;
}
}
PlaceholderFragment.java
/**
* A placeholder fragment containing a simple view.
*/
public class PlaceholderFragment extends Fragment {
String type;
private static final String ARG_SECTION_NUMBER = "section_number";
private PageViewModel pageViewModel;
public static PlaceholderFragment newInstance(int index) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle bundle = new Bundle();
bundle.putInt(ARG_SECTION_NUMBER, index);
fragment.setArguments(bundle);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pageViewModel = ViewModelProviders.of(this).get(PageViewModel.class);
int index = 1;
if (getArguments() != null) {
index = getArguments().getInt(ARG_SECTION_NUMBER);
}
pageViewModel.setIndex(index);
}
#Override
public View onCreateView(
#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_main, container, false);
final WebView webView = (WebView)root.findViewById(R.id.webView);
webView.setWebViewClient( new WebViewClient(){
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url){
webView.loadUrl(url);
return true;
}
});
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
pageViewModel.getText().observe(this, new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
type = s;
}
});
if(type == null)
{
type="1";
}
webView.loadUrl("https://my.domain/list.php?type="+type);
return root;
}
}
PageViewModel.java
public class PageViewModel extends ViewModel {
private MutableLiveData<Integer> mIndex = new MutableLiveData<>();
private LiveData<String> mText = Transformations.map(mIndex, new Function<Integer, String>() {
#Override
public String apply(Integer input) {
return input.toString();
}
});
public void setIndex(int index) {
mIndex.setValue(index);
}
public LiveData<String> getText() {
return mText;
}
}

You can add a loader till the webview loads in respective tabs. onPageFinished() is a callback when webview has completed loading
web_view.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, weburl: String) {
// Stop loading
}
}

My recommendation is that you should change
webView.loadUrl("https://my.domain/list.php?type="+type);
to
webView.loadUrl("https://my.domain/list.php?type=" + getArguments().getInt(ARG_SECTION_NUMBER));
and see how it works. If it works as you expected, I think you don't need the PageViewModel.java at all.
The root cause of unexpected behavior
In PageViewModel, the value of mIndex is updated by the following line of onCreate in PlaceholderFragment
pageViewModel.setIndex(index);
It also changes the value of mText, which is observed by the following block of onCreateView in PlaceholderFragment:
pageViewModel.getText().observe(this, new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
type = s;
}
});
Therefore, PageViewModel and PlaceholderFragment are in a race unexpectedly.
ViewPager creates more Fragment early, as written in setOffscreenPageLimit. It is not a good idea to update the value of mIndex in onCreate of PlaceholderFragment.

Related

FragmentStateAdapter removing last tab instead of current ViewPager2

ViewPager2 is removing last tab instead of current tab, same problem was occurring when i was using viewpager.
Also when selected tab is last one it removes last tab correctly
dependency
implementation "androidx.viewpager2:viewpager2:1.0.0"
This is main activity code
MainActivity.java
public class MainActivity extends AppCompatActivity {
TabLayout tabLayout;
ViewPager2 viewPager;
ViewPagerAdapter adapter;
Button btnAddTab,btnRemoveCurrentTab;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = findViewById(R.id.view_pager);
tabLayout = findViewById(R.id.tabs);
btnAddTab=findViewById(R.id.btn_add);
btnRemoveCurrentTab=findViewById(R.id.btn_remove);
adapter=new ViewPagerAdapter(this);
viewPager.setAdapter(adapter);
new TabLayoutMediator(tabLayout, viewPager,
new TabLayoutMediator.TabConfigurationStrategy() {
#Override public void onConfigureTab(#NonNull TabLayout.Tab tab, int position) {
tab.setText("Store " + (position + 1));
}
}).attach();
btnRemoveCurrentTab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
adapter.removeFrag(tabLayout.getSelectedTabPosition());
}
});
btnAddTab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DynamicFragment fView = new DynamicFragment();
adapter.addFrag(fView,"Store "+(adapter.getmFragmentIdList().contains(adapter.getItemCount()+1)?adapter.getItemCount()+2:adapter.getItemCount()+1),(adapter.getmFragmentIdList().contains(adapter.getItemCount()+1)?adapter.getItemCount()+2:adapter.getItemCount()+1));
}
});
}
}
ViewPagerAdapter
This is FragentStateAdapter
public class ViewPagerAdapter extends FragmentStateAdapter {
private final List<DynamicFragment> mFragmentList = new ArrayList<>();
private final List<Integer> mFragmentIdList = new ArrayList<>();
public ViewPagerAdapter(#NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
#NonNull #Override public Fragment createFragment(int position) {
return DynamicFragment.newInstance(String.valueOf(position),mFragmentIdList.get(position));
}
public void addFrag(DynamicFragment fragment, String title, int id) {
mFragmentList.add(fragment);
Log.e("fragment id " ,""+id);
Log.e("fragment array " ,title+ mFragmentList.size());
mFragmentIdList.add(id);
notifyDataSetChanged();
}
public void removeFrag(int pos) {
Log.e("deleted frag",mFragmentIdList.get(pos)+" "+pos);
mFragmentList.remove(pos);
mFragmentIdList.remove(pos);
notifyDataSetChanged();
}
public List<Integer> getmFragmentIdList() {
return mFragmentIdList;
}
#Override
public long getItemId(int position) {
return super.getItemId(position);
}
#Override public int getItemCount() {
return mFragmentList.size();
}
}
Fragment
This is my dynamic fragment which i want to add and remove
public class DynamicFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
private static final String ARG_ID = "id";
private String sectionNumber;
int id;
TextView textView;
EditText editText1,editText2;
public DynamicFragment() {
// Required empty public constructor
}
public static DynamicFragment newInstance(String sectionNumber, int id) {
DynamicFragment fragment = new DynamicFragment();
Bundle args = new Bundle();
args.putString(ARG_SECTION_NUMBER, sectionNumber);
args.putInt(ARG_ID, id);
fragment.setArguments(args);
Log.e("StoreDynamic","dynamic new instance");
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView= inflater.inflate(R.layout.fragment_dynamic, container, false);
textView=rootView.findViewById(R.id.textView);
editText1=rootView.findViewById(R.id.et1);
editText2=rootView.findViewById(R.id.et2);
sectionNumber = getArguments().getString(ARG_SECTION_NUMBER);
id=getArguments().getInt(ARG_ID);
editText1.setText(id+" "+sectionNumber);
textView.setText(id+" "+sectionNumber);
return rootView;
}
}
I ran into the same problem and the solution to this question: remove fragment in viewPager2 use FragmentStateAdapter, but still display worked for me. Mostly the part about overriding the getItemId function to return something other than the position to identify the item because the item's position changes when adding and removing fragments.
You need to overwrite the methods getItemId() and containsItemId()
as shown in this post: https://stackoverflow.com/a/57944197/870242
items variable holds your fragment (mFragmentList )
private val pageIds= items.map { it.hashCode().toLong() }
override fun getItemId(position: Int): Long {
return items[position].hashCode().toLong() // make sure notifyDataSetChanged() works
}
override fun containsItem(itemId: Long): Boolean {
return pageIds.contains(itemId)
}

pass value from activity to fragment using bundle in tabbed activity

I am a java-illiterate, and still trying to develop a app for my personal use.
I have started with android-studio's "Tabbed-Activity", and mostly unaltered except a fragment and a bundle in MainActivity.
Here are my codes:
MainActivity
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
private static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//FloatingActionButton fab = findViewById(R.id.fab);
Bundle bundle = new Bundle();
bundle.putDouble("loclat", 25.4358);
bundle.putDouble("loclang",81.8463);
Fragment SunFragment = new SunFragment();
SunFragment.setArguments(bundle);
setContentView(R.layout.activity_main);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
}
}
SectionsPagerAdapter
public class SectionsPagerAdapter extends FragmentPagerAdapter {
#StringRes
private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2, R.string.tab_text_3};
private final Context mContext;
public SectionsPagerAdapter(Context context, FragmentManager fm) {
super(fm);
mContext = context;
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
//return PlaceholderFragment.newInstance(position + 1);
switch (position) {
case 0:
return new SunFragment();
//return PlaceholderFragment.newInstance(pos + 5);
case 1:
return PlaceholderFragment.newInstance(1);
//return SecondFragment.newInstance();
//return PlaceholderFragment.newInstance(pos + 1);
default:
return PlaceholderFragment.newInstance(2);
}
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return mContext.getResources().getString(TAB_TITLES[position]);
}
#Override
public int getCount() {
// Show 2 total pages.
return 3;
}
}
And finally, The SunFragment, where I want my bundled data from MainActivity:
public class SunFragment extends Fragment {
List<SunSession> sunsList;
Typeface sunfont;
Double Dlat;
Double Dlang;
//to be called by the MainActivity
public SunFragment() {
// Required empty public constructor
}
private static final String KEY_LOCATION_NAME = "location_name";
public String TAG ="SunFragment";
public String location;//="No location name found";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Retrieve location and camera position from saved instance state.
if (savedInstanceState != null) {
location = savedInstanceState.getCharSequence(KEY_LOCATION_NAME).toString();
System.out.println("OnCreate location "+location);
// Dlat = getArguments().getDouble("loclat");
//Dlang = getArguments().getDouble("loclang");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_sun, container, false);
//onSaveInstanceState(new Bundle());
if (getArguments() != null) {
Dlat = getArguments().getDouble("loclat");
Dlang = getArguments().getDouble("loclang");
} else {
Dlat=23.1;
Dlang=79.9864;
}
Log.e("Lat", Double.toString(Dlat));
I have followed this blog to make it, but no value is passed. Kindly help.
NB. This is a better described, and detailed question of my earlier question, which I understand, needs more code to be shown.
In your MainActivity, your sunFragment is unused. Remove this part:
/*Bundle bundle = new Bundle();
bundle.putDouble("loclat", 25.4358);
bundle.putDouble("loclang",81.8463);
Fragment SunFragment = new SunFragment();
SunFragment.setArguments(bundle);*/
You have to set bundle to fragment inside your SectionsPagerAdapter
case 0:
Bundle bundle = new Bundle();
bundle.putDouble("loclat", 25.4358);
bundle.putDouble("loclang",81.8463);
Fragment sunFragment = new SunFragment();
sunFragment.setArguments(bundle);
return sunFragment;
But if you need to set the bundle to fragment from MainActivity. Then use a callback in that purpose.
This way you can pass data from your mainActivity to fragment
MainActivity onCreate method
adapter = new Adapter(getChildFragmentManager());
SquadsTeamListFragment teamA =
SquadsTeamListFragment.newInstance(teamAData,teamBData
adapter.addFragment(teamA, teamAName);
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
use this adapter in your main activity
static class Adapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
Adapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position){
return mFragmentTitleList.get(position);
}
}
receive data to fragment (SquadsTeamListFragment .java)
public static SquadsTeamListFragment newInstance(String playerList, String
oppPlayerList) {
SquadsTeamListFragment fragment = new SquadsTeamListFragment();
Bundle args = new Bundle();
args.putString(ARG_TEAM_DATA, playerList);
args.putString(ARG_OPP_TEAM_DATA, oppPlayerList);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
playerList = getArguments().getString(ARG_TEAM_DATA);
oppPlayerList = getArguments().getString(ARG_OPP_TEAM_DATA);
}
}

Android Fragment with ViewPagers oncreateView Called in Wrong Fragment

I have a main activity which shows 3 fragments inside View Pagers with tabs.
mainActivity.java
public class mainActivity extends AppCompatActivity {
globalVariableActivity variable = new globalVariableActivity();
private APIService mAPIService;
private TextView mResponseTv;
private RecyclerView recyclerView;
private Token token = new Token("","","");
private Gson gson = new Gson();
private Context context=mainActivity.this;
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//check if token is still active
String current_token=token.getToken(context);
MyFirebaseInstanceIDService Fcm= new MyFirebaseInstanceIDService();
Fcm.onTokenRefresh(context,current_token);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new BeritaFragment(), "Berita");
adapter.addFragment(new DiskusiFragment(), "Diskusi");
adapter.addFragment(new PesanFragment(), "Pesan");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
//Toast.makeText(context,"Item " + position + " shown.", Toast.LENGTH_SHORT).show();
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) {
Toast.makeText(context,"Position : " + position + " Title : "+ mFragmentTitleList.get(position) + " shown.", Toast.LENGTH_SHORT).show();
return mFragmentTitleList.get(position);
}
}
interface LyfecycleListener {
void onCreatedView();
}
here's the first fragment code
beritaFragment.java
public class BeritaFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private APIService mAPIService = APIUtils.getAPIService();;
private Gson gson = new Gson();
private TextView createdAtText;
private TextView judulText;
private ImageView imageView;
private RecyclerView mRecyclerView;
private ListAdapter mListadapter;
private ArrayList<DataBerita> list_berita= new ArrayList<>();
private OnFragmentInteractionListener mListener;
public BeritaFragment() {
}
// TODO: Rename and change types and number of parameters
public static BeritaFragment newInstance(String param1, String param2) {
BeritaFragment fragment = new BeritaFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getBeritaTask getBerita= new getBeritaTask();
try {
Log.d("berita :", "On create 1");
getBerita.execute().get(10000, TimeUnit.MILLISECONDS);
Log.d("berita :", "On create 2");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_berita, container, false);
Log.d("Berita","On create view");
Toast.makeText(getActivity() ,"Berita Fragment onCreateView", Toast.LENGTH_SHORT).show();
ArrayList<DataBerita> data_berita;
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
judulText = (TextView)view.findViewById(R.id.summary_judul);
createdAtText = (TextView)view.findViewById(R.id.created_at);
//imageView = (ImageView)view.findViewById(R.id.gambar);
final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
//data_berita=getBeritaList();
Log.d("Berita","1");
Log.d("Berita List : ", list_berita.toString());
Log.d("Berita","3");
mListadapter = new ListAdapter(list_berita);
mRecyclerView.setAdapter(mListadapter);
//Log.d("Berita view :", view.toString());
return view;
}
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder>
{
private ArrayList<DataBerita> dataList;
public ListAdapter(ArrayList<DataBerita> data)
{
this.dataList = data;
}
public class ViewHolder extends RecyclerView.ViewHolder
{
TextView judulText;
TextView waktuText;
ImageView gambarView;
public ViewHolder(View itemView)
{
super(itemView);
this.judulText = (TextView) itemView.findViewById(R.id.summary_judul);
this.waktuText = (TextView) itemView.findViewById(R.id.created_at);
//this.gambarView = (ImageView) itemView.findViewById(R.id.gambar);
}
}
#Override
public ListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.berita_list_layout, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(ListAdapter.ViewHolder holder, final int position)
{
Uri ImageURI=Uri.parse(dataList.get(position).getGambar_utama());
holder.judulText.setText(dataList.get(position).getSummary_judul());
holder.waktuText.setText(dataList.get(position).getCreated_at());
//holder.gambarView.setImageURI(ImageURI);
holder.itemView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Toast.makeText(getActivity(), "Item " + position + " is clicked.", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount()
{
return dataList.size();
}
}
private class getBeritaTask extends AsyncTask<Void, Void, Void> {
protected void onPreExecute() {
Log.d("Berita","2.1");
}
protected Void doInBackground(Void... voids) {
mAPIService.getBeritaList().enqueue(new Callback<Berita>() {
#Override
public void onResponse(Call<Berita> call, Response<Berita> response) {
list_berita = new ArrayList<>();
DataBerita data_berita = new DataBerita("","","","");
String id_berita;
String judul;
String gambar_utama;
String created_at;
Log.d("Berita","2.2");
if(response.isSuccessful()) {
Berita body = gson.fromJson(response.body().toString(),Berita.class);
for (int i = 0; i < body.getList_berita().getData().size(); i ++) {
id_berita=body.getList_berita().getData().get(i).getId_berita();
judul=body.getList_berita().getData().get(i).getSummary_judul();
gambar_utama=body.getList_berita().getData().get(i).getGambar_utama();
created_at=body.getList_berita().getData().get(i).getCreated_at();
data_berita = new DataBerita(id_berita,judul,gambar_utama,created_at);
list_berita.add(data_berita);
}
Log.d("Berita List",list_berita.toString());
}else{
Log.d("Berita", "Fail");
}
}
#Override
public void onFailure(Call<Berita> call, Throwable t) {
Log.d("Berita Fail", t.getMessage());
}
});
return null;
}
}
here's the 2nd and 3rd fragment (these 2 fragments are still mostly empty, with code for toast and log only for now)
DiskusiFragment.java
public class DiskusiFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public DiskusiFragment() {
// Required empty public constructor
}
// TODO: Rename and change types and number of parameters
public static DiskusiFragment newInstance(String param1, String param2) {
DiskusiFragment fragment = new DiskusiFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Toast.makeText(getActivity() ,"Diskusi Fragment onCreateView", Toast.LENGTH_SHORT).show();
return inflater.inflate(R.layout.fragment_diskusi, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
here's the problem,
fragment onCreateView function seems to be called on / in the wrong fragment.
when I start the app here's what happened :
Item position 0 , 1, and 2 is called
1st fragment on create view is called, and 2nd fragment on create view is called immediately
what happens next, depends on what I do :
when I change from 1st fragment => 2nd fragment, 3rd fragment on create view is called
when I change from 1st fragment => 3rd fragment, 3rd fragment on create view is called
when I switch from 2nd fragment => 1st fragment, no fragment on create view called
when I switch from 2nd fragment => 3rd fragment, no fragment on create view called
when I switch from 3rd fragment => 2nd fragment, no fragment on create view called (or sometimes 1st fragment on create view is called)
when I change from 3rd fragment => 1st fragment, 1st fragment on create view called
is this what suppose (in regard to onCreateView function is called on the wrong fragment) to happen?
if not, where did I code wrong?
Thank you very much
*EDIT : this behaviour is normal, I'm really new to android. Very sorry for the inconvenience guys
The FragmentPagerAdapter keeps additional fragments, besides the one shown, in the resumed state.
If you want to initialize stuff in the fragment you should do it when
OnCreate is called.
Anything that is related to the UI been loaded properly should happen on
onViewCreated
In addition, if you want to receive more information about how to handle fragments inside a ViewPager
#Shreyas Shetty answered it really well on this thread
What do you mean by "wrong" fragment? View pager creates next fragment prior to navigating to it to make the transition smooth and quick. And when the fragment is created its lifecycle methods are called accordingly, there's nothing wrong with this behaviour. If you want to perform some action when the user swipes to specific fragment in your view pager, you can use OnPageChangeListener.

When the fragment changes tabs, the text doesn't change

When the screen updates and changes tabs, the text of the other tabs still have the characteristics of the first.
private int mPage;
public static FeedFrag newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
FeedFrag fragment = new FeedFrag();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage = getArguments().getInt(ARG_PAGE);
}
// Inflate the fragment layout we defined above for this fragment
// Set the associated text for the title
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.feed_frag, container, false);
TextView first = (TextView) view.findViewById(R.id.Feed);
first.setText("feed");
return view;
}
And this is another tab
public class InStockFrag extends Fragment {
public static final String ARG_PAGE = "ARG_PAGE";
private int mPage;
public static InStockFrag newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
InStockFrag fragment = new InStockFrag();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage = getArguments().getInt(ARG_PAGE);
}
// Inflate the fragment layout we defined above for this fragment
// Set the associated text for the title
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.in_stock_frag, container, false);
TextView second = (TextView) view.findViewById(R.id.InStock);
second.setText("In Stock");
return view;
}
}
The Main Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get the ViewPager and set it's PagerAdapter so that it can display items
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new SimpleFragmentPagerAdapter(getSupportFragmentManager()));
// Give the PagerSlidingTabStrip the ViewPager
PagerSlidingTabStrip tabsStrip = (PagerSlidingTabStrip) findViewById(R.id.tabs);
tabsStrip.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
// This method will be invoked when a new page becomes selected.
#Override
public void onPageSelected(int position) {
// Toast.makeText(getActivity().this, "Selected page positon: " + position, Toast.LENGTH_SHORT).show();
}
// This method will be invoked when the current page is scrolled
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// Code goes here
}
// Called when the scroll state changes:
// SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING
#Override
public void onPageScrollStateChanged(int state) {
// Code goes here
}
});
tabsStrip.setViewPager(viewPager);
}
SimpleFragmentAdapter:
public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[] { "Feed", "In Stock", "Upcoming" };
public SimpleFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
return FeedFrag.newInstance(position + 1);
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
The app returns the text on the 3 tabs as "feed" instead of the other words.
Yes, obviously. It's because you are not calling correctly your fragments inside the getItem method in your SimpleFragmentPagerAdapter: you were always calling the FeedFrag.
Try to change the code of your view pager adapter like this, and inside the getItem method, put the code to call your third fragment, the one that have title "Upcoming":
public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[] { "Feed", "In Stock", "Upcoming" };
public SimpleFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
if (position==0) {
return FeedFrag.newInstance(position + 1);
} else if (position == 1) {
return InStockFrag.newInstance(position + 1);
} else {
//HERE RETURN SAME METHOD OF UPCOMING FRAGMENT
}
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}

FragmentTabHost with own fragment stack for each tab

I have MainActivity which has FragmentTabHost with several tabs. Each fragment in tab can be replaced with another fragment, so if we navigate back, we will see first displayed fragment for this tab (own stack for each tab). I have a quite working solution.
The below example demonstrates TabHost with 2 tabs and fragment classes for the first tab.
Is there any simpler, better or more elegant way to achieve this result?
AbstractPrimaryFragment.java. This class is a root fragment class that replaces fragments inside it. Other tab fragment classes can extend this superclass.
public abstract class AbstractPrimaryFragment extends Fragment {
// Simple framelayout.
private static final int RES_ID = R.layout.primary_fragment_layout;
protected static final int CONTENT_LAYOUT_ID = R.id.primary_fragment_layout;
protected Fragment mActiveFragment;
public AbstractPrimaryFragment()
{
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.inflate(RES_ID, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
// Check if active fragment is in layout, if not, make default fragment for this tab.
mActiveFragment = getChildFragmentManager().findFragmentById(CONTENT_LAYOUT_ID);
if (mActiveFragment == null)
{
mActiveFragment = makeDefaultActiveFragment();
String tag = getDefaultFragmentTag();
getChildFragmentManager().beginTransaction().add(CONTENT_LAYOUT_ID, mActiveFragment, tag).commit();
}
}
public boolean onBackPressed()
{
boolean backPressed = false;
final FragmentManager fragmentManager = getChildFragmentManager();
if (fragmentManager.getBackStackEntryCount() > 0)
{
fragmentManager.addOnBackStackChangedListener(new OnBackStackChangedListener()
{
#Override
public void onBackStackChanged()
{
mActiveFragment = fragmentManager.findFragmentById(CONTENT_LAYOUT_ID);
fragmentManager.removeOnBackStackChangedListener(this);
}
});
fragmentManager.popBackStack();
backPressed = true;
}
return backPressed;
}
protected abstract Fragment makeDefaultActiveFragment();
protected abstract String getDefaultFragmentTag(); }
Tab1PrimaryFragment.java
public class Tab1PrimaryFragment extends AbstractPrimaryFragment implements OnTab1Fragment1Listener {
private static final String FRAGMENT1_TAG = "tab1_fragment1";
private static final String FRAGMENT2_TAG = "tab2_fragment2";
#Override
protected Fragment makeDefaultActiveFragment()
{
return new Tab1Fragment1();
}
#Override
protected String getDefaultFragmentTag()
{
return FRAGMENT1_TAG;
}
#Override
public void onTab1Fragment1ButtonClick(Tab1Fragment1 tab1Fragment1)
{
Tab1Fragment2 tab1Fragment2 = new Tab1Fragment2();
getChildFragmentManager().beginTransaction().replace(CONTENT_LAYOUT_ID, tab1Fragment2, FRAGMENT2_TAG).addToBackStack(tab1Fragment1.getTag()).commit();
mActiveFragment = tab1Fragment2;
}}
Tab1Fragment1.class (default active fragment)
public class Tab1Fragment1 extends Fragment {
public interface OnTab1Fragment1Listener
{
public void onTab1Fragment1ButtonClick(Tab1Fragment1 tab1Fragment1);
}
private OnTab1Fragment1Listener mOnTab1Fragment1Listener;
public void setOnTab1Fragment1Listener(OnTab1Fragment1Listener onTab1Fragment1Listener)
{
mOnTab1Fragment1Listener = onTab1Fragment1Listener;
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Fragment parentFragment = getParentFragment();
if (parentFragment != null && parentFragment instanceof OnTab1Fragment1Listener)
{
mOnTab1Fragment1Listener = (OnTab1Fragment1Listener) parentFragment;
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
Button button = new Button(getActivity());
button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
if(mOnTab1Fragment1Listener != null)
{
mOnTab1Fragment1Listener.onTab1Fragment1ButtonClick(Tab1Fragment1.this);
}
}
});
return button; }}
Tab1Fragment2.java. Dummy fragment. This fragment is displayed when onTab1Fragment1ButtonClick is called.
public class Tab1Fragment2 extends Fragment {}
And MainActivity.java
public class MainActivity extends FragmentActivity {
private static final int RES_ID = R.layout.main_activity;
private static final int TAB_CONTENT_ID = android.R.id.tabcontent;
private static final int TABHOST_ID = android.R.id.tabhost;
private static final String TAB1_PRIMARY_FRAGMENT_TAG = "tab1_primary_fragment";
private static final String TAB2_PRIMARY_FRAGMENT_TAG = "tab2_primary_fragment"
private FragmentTabHost mTabHost;
#Override
protected void onCreate(Bundle bundle)
{
super.onCreate(bundle);
setContentView(RES_ID);
initializeTabHost();
}
private void initializeTabHost()
{
mTabHost = (FragmentTabHost) findViewById(TABHOST_ID);
mTabHost.setup(this, getSupportFragmentManager(), TAB_CONTENT_ID);
LayoutInflater inflater = LayoutInflater.from(this);
mTabHost.addTab(mTabHost.newTabSpec(TAB1_PRIMARY_FRAGMENT_TAG).setIndicator(inflater.inflate(R.layout.smth1, null)), Tab1PrimaryFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec(TAB2_PRIMARY_FRAGMENT_TAG).setIndicator(inflater.inflate(R.layout.smth2, null)), Tab2PrimaryFragment.class, null);
}
#Override
public void onBackPressed()
{
Fragment fragment = getSupportFragmentManager().findFragmentById(TAB_CONTENT_ID);
if (fragment != null && fragment instanceof AbstractPrimaryFragment)
{
if (((AbstractPrimaryFragment) fragment).onBackPressed())
{
return;
}
}
super.onBackPressed();
}}

Categories

Resources