ListFragments Wrong Data Weird Pager - android

I hope someone can assist please. I have a Fragment hosting multiple list fragments using support library. The list fragments are supposed to display data that i retrieve form an async task in the parent fragment. I have been trying to figure out exactly how the data is being loaded because it is not loading correctly.
Each time the list display fragment is launched it preforms an async task to get and parse Json into an ArrayList <ArrayList <HashMap <String, String> > >
Each List fragment queries the parent fragment for data at its position in the ArrayList.
eg. For the 3rd page in it should retrieve arrList[2] which contains an `ArrayList <HashMap <String, String> > to display as a list.
The pager is acting weird. Maybe i am not understanding the lifecycle of the fragments or how the pager uses them. I have 7 Fragments. If i start on frag3 the pager will show fragment 3 with no data on it. It also loads fragment 2 and 4 with no data. If i go left to frag 1 it will display fragment 1 correctly and load fragment 0. I can properly switch to frag 0 but if i switch to frag 2 it loads data from frag 0 and loads frag 0's data into all of the rest of the views. If i go back and forth enough it will replace all data in every fragment with data from frag 0. I believe that it does not load data immediately because it does not have the data when the viewpager launches. I have not made it wait for the async task yet.
I thought that each fragment gets its view redrawn each time it is taken far enough from view. So i put Update in the onCreateView() of the fragment. I feel like this is a small thing that i have just misplaced or i am overlooking it. I tried to implement FragmentStatePagerAdapter but i do not think that i did it right.
Any Help is much Appreciated And i am very open to discussion if i am just doing things horribly wrong. I usually do. It never fails. Create something to find out i need to rewrite everything.
public class ListFragmentDisplay extends SherlockFragment {
public static final String TAG = "listFragmentDisplay";
Calendar calendar = Calendar.getInstance();
private int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
// listbyday is a list of hash maps each list of hash maps represents a day
// of the week with items for that Object
private ArrayList<ArrayList<HashMap<String, String>>> listByDay = null;
private String objectName = null;
private ViewPager pager;
private FragAdapter adapter;
public ArrayList<HashMap<String, String>> getList(int day) {
return listByDay.get(day);
}
private void getObjectName() {
barName = ((MainFragActivity) getActivity()).getobjectSelected();
}
public static ListFragmentDisplay newInstance() {
return new ListFragmentDisplay();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the ListView layout file.
initArrList();
getObjectName();
fillList();
return inflater.inflate(R.layout.list_view, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
pager = (ViewPager) view.findViewById(R.id.viewPager);
adapter =new FragAdapter(getChildFragmentManager());
if (pager.getAdapter() == null)
pager.setAdapter(adapter);
reload();
pager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageScrollStateChanged(int arg0) {}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {reload();}
#Override
public void onPageSelected(int arg0) {
}
});
pager.setCurrentItem(dayOfWeek-1);
}
private void initArrList() {
if (listByDay == null) {
listByDay = new ArrayList<ArrayList<HashMap<String, String>>>();
} else {
listByDay.clear();
}
for (int i = 0; i < 7; i++) {
ArrayList<HashMap<String, String>> hm = new ArrayList<HashMap<String, String>>();
listByDay.add(hm);
}
}
synchronized private void fillList() {
LoadWebTask lWT = new LoadWebTask();
executeAsyncTask(lWT, getSherlockActivity().getApplicationContext());
}
FragmentPager
public class FragAdapter extends FragmentPagerAdapter {
private static final String[] CONTENT = new String[] { "frag0", "frag1",
"frag2", "frag3", "frag4", "frag5", "frag6" };
public FragAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int arg0) {
return MyListFragment.newInstance(arg0);
}
#Override
public int getCount() {
return CONTENT.length;
}
#Override
public CharSequence getPageTitle(int position) {
return CONTENT[position % CONTENT.length];
}
}
ListFragment
public class MyListFragment extends SherlockListFragment {
public static final String NAME_TAG = "name";
public static final String DESCRIPTION_TAG = "description";
private static int dow;
public static final String TAG = "listFragment";
// Keys used in Hashmap that will be mapped to the rows
String[] dFrom = { NAME_TAG, DESCRIPTION_TAG };
private ArrayList<HashMap<String, String>> list;
int[] dTo = { R.id.name, R.id.description };
public void upDateList() {
//**************************Not really sure if this is how things are supposed
//** to be done. For my small data- set i feel like it will work but i would
//** be interested in knowing how else this might be done.
ListFragmentDisplay lFD = (ListFragmentDisplay) this
.getParentFragment();
dList = lFD.getList(dow);
}
public static MyListFragment newInstance(int pos) {
MyListFragment frag = new MyListFragment();
dow = pos;
return (frag);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
upDateList();
View results = inflater.inflate(R.layout.list_fragment, container,
false);
SimpleAdapter adapter = new SimpleAdapter(getParentFragment()
.getActivity(), list, R.layout.listrow, dFrom, dTo);
setListAdapter(adapter);
return results;
}
}
Edit. Solved Code: In List Fragment
The Initial Question has been solved. I am only in the process of implementing the onPostExecute callback to the ListFragmentDisplay. Much Thanks to Luksprog for solving my very noobish mistake. I made dow static without knowing its affect. I think it was actually something that Eclipse offered to solve a conflict. I should have read it closer.
public class MyListFragment extends SherlockListFragment {
public static final String NAME_TAG = "name";
public static final String DESCRIPTION_TAG = "description";
public static final String TAG = "listFragment";
// Keys used in Hashmap that will be mapped to the rows
String[] dFrom = { NAME_TAG, DESCRIPTION_TAG };
private ArrayList<HashMap<String, String>> list;
int[] dTo = { R.id.name, R.id.description };
SimpleAdapter adapter = null; **NEW**
public void upDateList() {
ListFragmentDisplay lFD = (ListFragmentDisplay) this
.getParentFragment();
dList = lFD.getList(getArguments().getInt(TAG)); **NEW**
if(adapter != null) **NEW**
adapter.notifyDataSetChanged(); **NEW**
}
public static MyListFragment newInstance(int pos) {
MyListFragment frag = new MyListFragment();
Bundle args = new Bundle(); **NEW**
args.putInt(TAG, pos); **NEW**
frag.setArguments(args); **NEW**
return (frag);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
upDateList();
View results = inflater.inflate(R.layout.list_fragment, container,
false);
adapter = new SimpleAdapter(getParentFragment()
.getActivity(), list, R.layout.listrow, dFrom, dTo);
setListAdapter(adapter);
return results;
}
}

Is there any reason why you made the dow variable from MyListFragment as static? With the static keyword your fragments from the ViewPager will share their position so you'll call the lFD.getList(dow); method with the wrong position most of the cases. Make dow a private instance field: private int dow;
About the rest of the code, it looks ok, see if the change above solves the problem. To update your data in the inner fragments you could follow this scenario:
start with an empty list of data in ListFragmentDisplay and start the task
initially, your inner ListFragmnents will see that the data list is empty so you'll initialize them with an empty list(the getList(int day) method should just return an empty list if there is no data in the listByDay field)
your task now finishes. Suppose you have a callback from the onPostExecute method of the AsyncTask. In that callback which the ListFragmentDisplay will implement you'll update every Fragment from the ViewPager which is either currently visible to the user or it's in the FragmentPagerAdapter alive(so each Fragment which is not null and its getView() method doesn't return null from the ViewPager will be updated). The other Fragments will self update because the onCreateView method will need to be called for them and you have the updateList call in there.
For the point above keep in mind that calling the updateList method will not update a visible Fragment because in that method you just update the list of the Fragment you don't call notifyDataSetChanged on the adapter to let it know that the data has changed.

Related

ListFragment sometimes skips code in onLoadFinished() method of Loader

I have a ListFragment which fetches data from the net using a Loader. I use a new instance of this ListFragment in every page of my ViewPager. It works perfectly, but when I use TabLayout or moves pages quickly, the Fragment keeps loading and does not display the data in the ListView.
When I checked using log messages, I found that the ListFragment skips some lines of code in the onLoadFinished() method. It does not make the ProgressBar invisible. It does add items to Adapter, but it is not being displayed in the ListView. This problem also happens in the first page of the ViewPager.
Is there any specific rule to be followed when using ListFragments in a ViewPager?
Here is the ListFragment class. If you look at the onLoadFinished() method, you can see the lines causing problem:
public class ListViewFragment extends ListFragment
implements LoaderManager.LoaderCallbacks<List<GameNews>> {
public static ListViewFragment newInstance(String url) {
Log.d("ListViewFragment", "newInstance created");
ListViewFragment f = new ListViewFragment();
// Supply url input as an argument.
Bundle args = new Bundle();
args.putString("url", url);
f.setArguments(args);
return f;
}
List<GameNews> TotalNews;
ListView gameListView;
LinearLayout emptyView;
Button retryButton;
ListAdapter adapter ;
private View progressBar;
final private int game_loader = 0;
ArrayList<String> urls = new ArrayList<>();
String mUrlString;
int index;
//LIFE CYCLE OF FRAGMENT
//------------------------------------------------------------------
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUrlString = getArguments().getString("url");
urls.add(mUrlString);
TotalNews = new ArrayList<GameNews>();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_list_view, container, false);
ArrayList<GameNews> gameList = new ArrayList<>();
adapter = new ListAdapter(getActivity(), gameList);
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
emptyView = (LinearLayout)
view.findViewById(R.id.no_internet_view);
progressBar = view.findViewById(R.id.progress_bar);
retryButton = (Button) view.findViewById(R.id.retry_button);
gameListView = getListView();
emptyView.setVisibility(View.INVISIBLE);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setListAdapter(adapter);
//If connected to net start the loader
if (isConnected()) {
getActivity().getSupportLoaderManager().restartLoader(game_loader,
null,
ListViewFragment.this);
}
}
//OVERRIDED METHODS OF LOADERMANAGER
//---------------------------------------------------------------------
#Override
public android.support.v4.content.Loader<List<GameNews>> onCreateLoader(int i, Bundle bundle) {
AdManager manager = new AdManager(getActivity());
return new FragmentLoader(getActivity(), urls, 1000);
}
//HERE IS THE PROBLEM PLEASE FOCUS INSIDE THIS METHOD
//-------------------------------------------------------
#Override
public void onLoadFinished(Loader<List<GameNews>> loader, List<GameNews> games) {
progressBar.setVisibility(View.INVISIBLE); //This line of code is not executed
adapter.clear();
TotalNews.addAll(games);
adapter.addAll(games);//And the listView is not populated
}
//-------------------------------------------------------
#Override
public void onLoaderReset(Loader<List<GameNews>> loader) {
adapter.clear();
}
//REUSABLE METHODS
//------------------------------------------------------------------
//Method checks if there is internet
public boolean isConnected() {
ConnectivityManager manager = (ConnectivityManager)
getActivity().getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo info = manager.getActiveNetworkInfo();
if (info != null && info.isConnected()) {
return true;
}
else {
return false;
}
}
}
Your Fragment class is using the Activity's LoaderManager:
getActivity().getSupportLoaderManager().restartLoader(...);
And each instance is using the same ID in its restartLoader() call:
final private int game_loader = 0;
This means that each Fragment instance was using and restarting the same Loader over and over again, leading to the weird behavior you observed.
The solution is quite simple: use Fragment's local LoaderManager, instead of the Activity's.
getLoaderManager().restartLoader(...);
With this, you don't need to worry about changing the ID in each instance, since Loaders are unique to their Fragment, and the Loader will be properly handled over the Fragment's lifetime, which would likely not have been the case when using the Activity's LoaderManager.

Using ViewPager with ListFragment and CursorAdapter

I have an existing app displaying five different lists of entries from a database. It uses a left drawer to choose which list is displayed.
I would like to use ViewPager to these lists, but have a really hard time figuring out how this works. Unfortunately, I cannot find a tutorial that addresses this.
I have a MainActivity to which I connect a viewpagerAdapter
MainActivity extends AppCompatActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
...
// Setting the viewpager
mPager = (ViewPager) findViewById(R.id.pager_container_home);
mPagerAdapter = new EntriesListPagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
...
}
private class EntriesListPagerAdapter extends FragmentPagerAdapter {
...
#Override
public Object instantiateItem(ViewGroup container, int position) {
// What to put here???
return view;
}
}
I have a ListFragment class getting its data from a ResourceCursorAdapter (called EntriesCursorAdapter). It is a long class, so I give some parts to give you an idea.
public class EntriesListFragment extends ListFragment {
...
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
...
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mEntriesCursorAdapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
mEntriesCursorAdapter.swapCursor(Constants.EMPTY_CURSOR);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
setHasOptionsMenu(true);
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mUri = savedInstanceState.getParcelable(STATE_URI);
mShowFeedInfo = savedInstanceState.getBoolean(STATE_SHOW_FEED_INFO);
mListDisplayDate = savedInstanceState.getLong(STATE_LIST_DISPLAY_DATE);
mEntriesCursorAdapter = new EntriesCursorAdapter(getActivity(), mUri, Constants.EMPTY_CURSOR, mShowFeedInfo);
}
}
#Override
public View inflateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_entry_list, container, true);
if (mEntriesCursorAdapter != null) {
setListAdapter(mEntriesCursorAdapter);
}
mListView = (ListView) rootView.findViewById(android.R.id.list);
...
}
public void setData(Uri uri, boolean showFeedInfo) {
mUri = uri;
mShowFeedInfo = showFeedInfo;
mEntriesCursorAdapter = new EntriesCursorAdapter(getActivity(), mUri, Constants.EMPTY_CURSOR, mShowFeedInfo);
}
Can you help me how to create five instances of the listfragment (with cursoradapter) and connect it to the ViewPager in the MainActivity? Any hint how to proceed is welcome.
Update: I noticed that the FragmentPagerAdapter is from the support.v4 library. If I am to use this, It looks like I have to use the ListFragment from support.v4 as well, including the LoaderManager. Unfortunately, the LoaderManager is not easily upgraded to support.v4. Any thoughts are welcome.
I got it solved. I will give the main pointers.
First, read this tutorial, because the given structure works. http://www.truiton.com/2013/05/android-fragmentpageradapter-example/
Second, check that all your imports are from the support.v4 library. This means the FragmentActivity (AppCompatActivity in the case above), ListFragment, Loader, LoaderManager and CursorLoader. I spent quite some time trying to figure out what was wrong with the code, while all the time I still had the Loader and CursorLoader from the wrong library.
Third, the MainActivity is where the FragmentPagerAdapter is placed, like:
MainActivity extends AppCompatActivity {
static final int ITEMS = 5; // number of lists
...
#Override
protected void onCreate(Bundle savedInstanceState) {
...
// Setting the viewpager
mPager = (ViewPager) findViewById(R.id.pager_container_home);
mPagerAdapter = new EntriesListPagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
...
}
public class EntriesListPagerAdapter extends FragmentPagerAdapter {
public EntriesListPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public int getCount() {
return ITEMS;
}
#Override
public Fragment getItem(int position) {
return EntriesListFragment.init(position);
}
}
}
Fourth, the ListFragment has to change. It has to be able to be used several times in order to support the number of different lists in the ViewPager. I will give the importants methods/elements.
public class EntriesListFragment extends ListFragment {
// Loader to get the data from database for the list. Called from startLoaders();
private final LoaderManager.LoaderCallbacks<Cursor> mEntriesLoader = new LoaderManager.LoaderCallbacks<Cursor>() {...}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Getting the page number when created
pageViewerFragmentNum = getArguments() != null ? getArguments().getInt("val") : 1;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_entry_list, container, false); // orig was 'true'
mListView = (ListView) rootView.findViewById(android.R.id.list);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
Log.e(TAG, "onActivityCreated");
super.onActivityCreated(savedInstanceState);
// Setting the adapter for each of the Feeds
// The used feedId is the pageViewerFragmentNum + 1
String FeedId = String.valueOf(pageViewerFragmentNum+1);
mUri = EntryColumns.ENTRIES_FOR_FEED_CONTENT_URI(FeedId);
// setting the adapter for the list
mEntriesCursorAdapter = new EntriesCursorAdapter(getActivity(), mUri,
Constants.EMPTY_CURSOR);
setListAdapter(mEntriesCursorAdapter);
startLoaders();
}
// Initialise the new listFragment for each Page. Notice the static!
public static EntriesListFragment init(int positie) {
EntriesListFragment viewPagerFragmentList = new EntriesListFragment();
// Supply val input as an argument.
Bundle args = new Bundle();
args.putInt("val", positie);
viewPagerFragmentList.setArguments(args);
return viewPagerFragmentList;
}
private void startLoaders() {
LoaderManager loaderManager = getLoaderManager();
loaderManager.restartLoader(ENTRIES_LOADER_ID, null, mEntriesLoader);
}
}
Notice that the code given above is not complete. The tutorial mentioned earlier is, but I just tried to show you the main ingredients to get you started if you get stuck on this like I did.

Viewpager gets the wrong page

I have looked in several topics like this but didn't see how to fix my problem
I have a resturant for say.. with dynamic number of categories.. I put all the categories in a list.. and create fragments by from those categories
so I cant just
case 0 : fragment0
case 1 :frament 1
because I dont know how much categories I have untill runtime
class MyPageAdapter extends FragmentStatePagerAdapter {
private List<MyFragment> fragments = new ArrayList<>();
private List<menuCat> Categories = new ArrayList<>();
public MyPageAdapter(FragmentManager fm, List<menuCat> Categories) {
super(fm);
this.Categories = Categories;
for (int i = 0; i<Categories.size();i++)
{
fragments.add(MyFragment.newInstance(Categories.get(i)));
}
}
#Override
public String getPageTitle(int position)
{
return Categories.get(position).catName();
}
#Override
public MyFragment getItem(int position) {
return this.fragments.get(position);
}
#Override
public int getCount() {
return this.fragments.size();
}
MyFragment.class
public class MyFragment extends Fragment {
public static final MyFragment newInstance(menuCat category)
{
Bundle bun = new Bundle();
bun.putString("category", category.toJson());
MyFragment f = new MyFragment();
f.setArguments(bun);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_my, container, false);
String json = getArguments().getString("category");
menuCat category = menuCat.fromJson(json);
System.out.println(category.catName());
ArrayList<Card> cards = new ArrayList<Card>();
for(menuItem item : category.getItems())
{
Card card = new Card(getActivity());
// Create a CardHeader
CardHeader header = new CardHeader(getActivity());
// Add Header to card
header.setTitle(item.getName());
card.setTitle(item.getPrice());
card.addCardHeader(header);
CardThumbnail thumb = new CardThumbnail(getActivity());
//thumb.setDrawableResource(listImages[i]);
//card.addCardThumbnail(thumb);
cards.add(card);
}
CardArrayAdapter mCardArrayAdapter = new CardArrayAdapter(getActivity(), cards);
CardListView listView = (CardListView) getActivity().findViewById(R.id.myList);
if (listView != null) {
listView.setAdapter(mCardArrayAdapter);
}
return v;
}
}
this is my adapter, my problem is for example
if I am in page 1 and I need page 3 data.. if I will go to page 2.. it will display data of page 3 OR if I go to page 5 then go backward.. to 4 it will also show data of page 3.. I mean it gets me like the data of the next page instead of current one.
Creating all of your fragments in the constructor is very poor design, as you're creating references to these objects which will later be attached to an Activity, but when they are detached, you continue to hold the reference. In the end, this is going to cause you a lot of frustration with memory leaks.
Is it not possible to simply remove fragments and change your methods to the following:
#Override
public MyFragment getItem(int position) {
return MyFragment.newInstance(Categories.get(position));
}
#Override
public int getCount() {
return Categories.size();
}
I'm not certain this will solve all of your problems, but it is a start.

ViewPager Fragments doesn't show correct data

i'm pretty new with Fragments and ViewPager. I'm using ActionBarSherlock and ViewPageIndicator from Jack Wharton.
I've started with a standard Android MasterDetailFlow Activity and did try to modify it to use a ViewPager in the detail part.
I'm using the standard DummyContent to provide some static data but i've replaced the DummyItem with my "Survey"-Library i have to use in this app. DummyContent provides a public static ArrayList which i use to fill the list in the list activity. After i choose a survey in this list, the corresponding questions should be shown in the view pager.
Here is the code of my QuestionActivity.java which hosts the question fragments.
public class QuestionActivity extends SherlockFragmentActivity {
private QuestionsFragmentPagerAdapter mAdapter;
private PageIndicator mIndicator;
private ViewPager mPager;
private String surveyName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_viewpager);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
surveyName = getIntent().getExtras().getString(ItemDetailFragment.ARG_SURVEY_NAME);
mAdapter = new QuestionsFragmentPagerAdapter(getSupportFragmentManager(), DummyContent.mgr.getSurvey(surveyName).getQuestions());
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mIndicator = (PageIndicator) findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
}
}
QuestionsFragmentPagerAdapter.java
public class QuestionsFragmentPagerAdapter extends FragmentPagerAdapter {
ArrayList<Question> questions;
public QuestionsFragmentPagerAdapter(FragmentManager fm, List<Question> questions) {
super(fm);
this.questions = (ArrayList<Question>) questions;
}
#Override
public Fragment getItem(int position) {
Fragment f = QuestionFragment.newInstance(questions.get(position));
return f;
}
#Override
public int getCount() {
return questions.size();
}
}
QuestionFragment.java
public class QuestionFragment extends SherlockListFragment {
protected enum QuestionType {
FT, SC, MC;
}
public final static String ARG_QUESTION_QUESTION = "question_question";
public final static String ARG_QUESTION_TYPE = "question_type";
public final static String ARG_QUESTION_ANSWERINGOPTIONS = "question_answeringptions";
private TextView lblQuestion;
private EditText txtAnswer;
private ListView listAnswers;
private ArrayAdapter<String> listAdapter;
private Question question;
private int listLayout;
/**
*
* #param question
* #return
*/
public static QuestionFragment newInstance(Question question) {
QuestionFragment fragment = new QuestionFragment();
// Creates a Bundle with all informations available in the question obj.
Bundle args = createBundleFromQuestion(question);
fragment.setArguments(args);
return fragment;
}
/**
*
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Creates the question object from the given arguments.
// I know this isn't a good solution, i will implement the
// Parcelable asap i have solved the current issues.
//
createQuestionFromBundle(getArguments());
// String questionXml = getArguments() != null ? getArguments().getString(ARG_QUESTION_XML) : null;
// this.question = (Question) MyXmlSerializer.deserialize(questionXml, Question.class);
}
/**
* Creates a the Question object form the Bundle.
* #param extras
*/
private void createQuestionFromBundle(Bundle extras) {
// Think we don't need it here. The field question gets instantiated.
}
/**
*
*/
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.answer_question, null);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initWidgets();
setCorrectLayout();
initContent();
}
private void initContent() {
String questionStr = question.getQuestion();
lblQuestion.setText(questionStr);
if(question instanceof FTQuestion) {
} else if (question instanceof ClosedQuestion) {
listAdapter = new ArrayAdapter<String>(getActivity(), listLayout);
List<Answer> answeringOptions = question.getAnswers();
for(Answer answer : answeringOptions) {
listAdapter.add(answer.getAnswer());
}
listAnswers.setAdapter(listAdapter);
}
}
/**
*
*/
private void initWidgets() {
listAnswers = getListView();
lblQuestion = (TextView) getActivity().findViewById(R.id.lblQuestion);
txtAnswer = (EditText) getActivity().findViewById(R.id.txtAnswer);
}
/**
* Sets the FT/SC/MC layout
*/
private void setCorrectLayout() {
if(question instanceof FTQuestion) {
setFtLayout();
} else if (question instanceof SCQuestion) {
setScLayout();
} else if (question instanceof MCQuestion) {
setMcLayout();
}
}
/**
*
*/
private void setFtLayout() {
if(listAnswers.getVisibility()!=ListView.INVISIBLE && listAnswers.getVisibility()!=ListView.GONE) {
listAnswers.setVisibility(ListView.GONE);
}
}
/**
*
*/
private void setScLayout() {
listLayout = R.layout.answer_question_single_choice_list_row;
listAnswers.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
if(txtAnswer.getVisibility() == TextView.VISIBLE) txtAnswer.setVisibility(TextView.GONE);
}
/**
*
*/
private void setMcLayout() {
listLayout = R.layout.answer_question_multiple_choice_list_row;
listAnswers.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
if(txtAnswer.getVisibility() == TextView.VISIBLE) txtAnswer.setVisibility(TextView.GONE);
}
}
Choosing the right survey in the list works fine, but now the questions are displayed totaly wrong.
Actually there should be now 3 pages with 3 different questions. On the first page there should be a label with a question"Eine tolle FT Frage?" and below this label an EditText. On the second page there should be a label with a question "Eine tolle SC Frage?" and below a list with the answering options. On page three the should have the question "Eine tolle MC Frage?" and also a list below it with the same answering options as on page two.
The screenshos show a transition between the pages in the order: 1 -> 2 -> 3 -> 2 -> 1 -> 2.
you can see, that it does not appear in a way i described it above. the content of the pages does also change during the transition. i believe that there could be a problem with the DummyContent because it's static?!
If i create a survey with just one question, everything works fine...
Okay i've found the answer:
i wanted to initialize the used widgets in the onCreateView Callback. But then i always got "java.lang.IllegalStateException: Content view not yet created". A closer look showed, that this was just because of the getListView() method.
Now i switched the initialization of the widgets to the onCreateView() Callback but the getListView() i left in onActivityCreated().
Now everything works fine, and the fragments are displayed correctly!
That's how it looks right now:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.answer_question, null);
lblQuestion = (TextView) v.findViewById(R.id.lblQuestion);
txtAnswer = (EditText) v.findViewById(R.id.txtAnswer);
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
listAnswers = getListView();
setCorrectLayout();
initContent();
}
Add mIndicator.setOnPageChangeListener to your indicator.And send BroadCast inside for current page.
indicator.setOnPageChangeListener(new OnPageChangeListener()
{
#Override
public void onPageSelected(int page) {
switch (page) {
case 0:
sendBroadcast(intent)// update your content.When broadcast come set correct layout.
break;
default:
break;
}
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
#Override
public void onPageScrollStateChanged(int arg0) {}
});
Implement broadcast listener to the fragment.
Move your init methods(initWidgets(),initContent())
to a OnCreateView method
It should works

getItem() calling multiple time in FragmentPagerAdapter

I am developing application using viewpager with fragment.In my application i have a items which i showing in List.After that when i click i have calling SherlockFragmentActivity which calling ViewPager with adapter.Now the problem is getItem in FragmentPagerAdapter give multiple position at a single time.Also when i flip backword then also giveing wrong position.Here is my code
ViewPager Code:-
private void initialisePaging() {
//Adapter Context;
this.mPagerAdapter = new MyPagerAdapter(
super.getSupportFragmentManager(), getApplicationContext(),
title, link, description);
ViewPager pager = (ViewPager) super.findViewById(R.id.viewpager);
pager.setAdapter(this.mPagerAdapter);
//Take position from ListView & set postion .
pager.setCurrentItem(post_position);
}
My Adapter Class which responsible for set fragment:-
Problem:- The problem is getItem Calling 3 time & suppose i click on 4 item its giving me 3,4,5 number.
public MyPagerAdapter(FragmentManager fm, Context cont,
ArrayList<String> title, ArrayList<String> link,
ArrayList<String> description) {
super(fm);
this.context = cont;
this.key_desc = description;
this.key_link = link;
this.key_title = title;
viewPagerApplication = (RssItem) cont;
}
#Override
public Fragment getItem(int position) {
return Fragment0.newInstance(position, this.context, key_title,
key_link, key_desc);
}
#Override
public int getCount() {
return key_title.size();
}
My Fragment Class:-
Problem:-Here if i show postion in textview its correct position but if i want take position in logcat for further parsing its giving me again 4,3,5 number which is also diffrent from getItem();
public static Fragment0 newInstance(int num,Context cont, ArrayList<String> key_title, ArrayList<String> key_link, ArrayList<String> key_desc) {
context=cont;
Fragment0 f = new Fragment0();
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
};
public int getShownIndex() {
return getArguments().getInt("num", 0);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.newsdetailfragment_screen, container, false);
tv = v.findViewById(R.id.headingtextview_id);
((TextView)tv).setText(String.valueOf(getShownIndex()));
((TextView)tv).setTextColor(Color.BLACK);
((TextView)tv).setTextSize(20);
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
Now kindly let me know where i am wrong & how can i get only one exact position for further process.
Inside of getItem(), the position parameter is the position that is in need of rendering. It is NOT the position of the currently focused item that the user would see. The pages to the left and right of the currently displayed view need to be pre rendered in memory so that the animations to those screens will be smooth. To get the item at current position use:
pager.getCurrentItem();
If you need an actual position of the page you can implement onPageChangeListener
pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
}
position in onPageSelected will give an accurate current position of the page.

Categories

Resources