is there an easier way to do this? radiogroups/buttons - android - android

I have two fragments and first fragment I have two pages and each page has at least two radio buttons with a question and those radio buttons are to choose your answer.
At the moment I have to use the if else function and using the setText to set the question and the answers for the radio button and when the right answer is clicked nothing will show until you go to the last page and click on show result.
Right now I have to keep on using if else and using setOnClickListener for all of them.
Also, by using the setOnClickListener it'll send a +1 result to my result page's variable.
Is there an easier way to do this?
This is what my code looks like
if(fragmentNumber == 0)
{
ask_question.setText("Question1?");
rb1.setText("Answer1");
rb2.setText("Answer2");
rb1.setOnClickListener(new android.view.View.OnClickListener() {
#Override
public void onClick(View v) {
ResultsFragment.Q1 = 1;
}
});
}
else if(fragmentNumber == 1)
{
ask_question.setText("Question2?");
rb1.setText("Answer2-1");
rb2.setText("Answer2-2");
rb2.setOnClickListener(new android.view.View.OnClickListener() {
#Override
public void onClick(View v) {
ResultsFragment.Q2 = 1;
}
});
}
Other than looking for an easier way to do this, I ran into another problem too.
Let me use examples.
E.g. if Q1 I got it right and Q2 I got it wrong when I go to show result I will get 1/2 which is good but if I go back to Q1 and click on the wrong answer on purpose then go back to show result, it'll still show 1/2 instead of 0/2 which means if the 1 is set into the variable then it'll stay there. I know if I use the setOnclickListener then I can set the other radioButtons == 0 but that means inside each if statement there will be LOTS setonClickListner this is kind of another reason I'm seeking another easier result.
Thanks in advance.

Looking for an easier way? Ok. In my opinion you should have a fragment(custom QAFragment) with only one page for a question and the answers.
public class QuestionFragment extends Fragment {
public static QuestionFragment newInstance(String questionText, String[] answerArray) {
QuestionFragment f = new QuestionFragment();
Bundle args = new Bundle();
args.putString("questionText", questionText);
args.putStringArray("answerArray", answerArray);
f.setArguments(args);
return f;
}
public String getQuestionText() {
return getArguments().getString("questionText");
}
public String[] getAnswerArray() {
return getArguments().getStringArray("answerArray");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View content = null;
// TODO: inflate your content here, put your radios and question text
final String questionText = getQuestionText();
String[] answerArray = getAnswerArray();
// TODO: set your question text with questionText value
// TODO: set your asnwers with answerArray values
RadioGroup radioGroup = null;
// TODO: keep your radios with this radioGroup
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup radioGroup, int radioButtonID) {
String selectedAnswer = null;
// TODO: if/else or switch statement on radioButtonId to get the selected answer
// Post the result to main activity to do extra operations or open new page.
((MainActivity)getActivity()).postQAResult(questionText, selectedAnswer);
}
});
return content;
}
}
Add postQAResult method to your main activity to listen callbacks from your fragment.
public void postQAResult(String question, String asnwer) {
// TODO: handle answer for the question.
// For example if you need to store answer you can use SharedPreferences to save.
// Or you can ask different questions for given answer.
}
Now you can add this qa fragment from your activity when you need a new question/answer page. for example;
String questionText = "Any problem?";
String[] answerArray = new String[]{"Yes","No"};
QuestionFragment questionFragment = QuestionFragment.newInstance(questionText, answerArray);
getFragmentManager().beginTransaction().add(android.R.id.content, questionFragment, "UNIQUE_TAG_FOR_YOUR_PAGE").commit();
You may need to show the previous question to the user. Then do not remove your qa fragments and put them to backstack while adding them.

Related

Adding list items to favorite facing error, doesn't persist state

I have a method to add favorites from a search list.
This code allows to click on listview and call listener accordingly weather it is search listview or mytour Listview.
holder.imgaddFavourite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (tourList.get(position).getFav().equalsIgnoreCase("0")) {
listener.onFavourited(tourList.get(position), true);
holder.imgaddFavourite.setImageResource(R.drawable.faved);
} else {
listener.onFavourited(tourList.get(position), false);
holder.imgFavourite.setImageResource(R.drawable.not_faved);
}
}
});
Below is the code for mytourList which works perfectly:
#Override
public void onFavourited(final Tour tour, final boolean fav) {
new SetFavourite(new SetFavourite.OnFavouriteSet() {
#Override
public void onFavouriteSet(Boolean response) {
int index = listTour.indexOf(tour);
tour.setFav(fav ? "1" : "0");
listTour.set(index, tour);
}
}, fav).execute(tour.getId(), application.getUser().getUid());
}
This code persist favourite state and got no problem.
Below is my code for adding favorites for search items list.
public void onFavourited(final Tour tour, final boolean fav) {
int index = searchOptions.getSearchedTours().indexOf(tour);
tour.setFav(fav ? "1" : "0");
searchOptions.getSearchedTours().get(index).setFav(fav ? "1" : "0");
searchOptions.getSearchedTours().set(index, tour);
}
I am able to click on and add it to favorites, but if I open another tab and reopen that list again, the state is lost. I guess it is cause it's not saving state globally. I've searched for similar answers but none of them helped.
Any help would be appreciated.
You are storing the state of wheather an item is favourite or not in a Boolean variable which is not a persistent storage. It will not be same when you close and reopen the app.
You should store the favourite items on SharedPreferences or in SQL Database which are persistent storage. In that way you can add and remove the data anytime you want, and it will be persisted.
Hope this helps, if you have any doubt, do let me know.
I think you are using ViewPager to handle fragments and always create new fragment when page changed. Therefore state cannot be retained. Try below method in the adapter of ViewPager:
Add variable to keep your desired fragment.
SearchTourFragment searchTourFragment = null;
In getItem(), create your desired fragment only when it is null.
if(searchTourFragment == null){
searchTourFragment = SearchTourFragment.newInstance();
}
return searchTourFragment;
Avoid deleting your desired fragment by override destroyItem().
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
if(position != POSITION_OF_SEARCHTOURFRAGMENT) container.removeView((View)object);
}
This is trying to keep your desired fragment from page change. But if you start another Activity and then back, the fragment may not be retained. Hope that helps!

Get Fragments edittext values on Activity button click event

I have a viewpager containing 2 fragments and each fragment contains a edittext. When user clicks the button in the activity i need to get the edittext values in the fragments to activity. I referred to this documentation Communicating with Other Fragments, it is something like when user click the list item within the fragment i will get the values in the activity.But in my case the button is in activity.Could anyone suggest the right way of doing this
You can either do it like Christopher Francisco suggested (with TextWatchers) or you could assign IDs to the EditTexts and retrieve their data like this (in the Buttons onClickListener inside the Activity):
String editText1Data = ((EditText) findViewById(R.id.editText1)).getText().toString();
String editText2Data = ((EditText) findViewById(R.id.editText2)).getText().toString();
....
Instead of the Activity asking the Fragment for data, pass data from Fragment to Activity (without the need of it to ask).
What I mean is, add a TextWatcher interface to the EditText and afterTextChanged() use an interface (read again http://developer.android.com/training/basics/fragments/communicating.html) to pass it to the Activity. When the user press the button, you dont have to retrieve the value from the fragments, cause you already have them, you just have to apply the logic.
For example:
// Inside Activity, it should implement FragmentInterface1, FragmentInterface2
private String str1;
private String str2
#Override
public void onFragment1EditTextChanged(String string) {
str1 = string;
}
#Override
public void onFragment2EditTextChanged(String string) {
str2 = string;
}
// This is for each Fragment1 and Fragment2, just change the number acordingly
private FragmentInterface1 listener = null;
#Override
public View onCreateView(/*params*/) {
// inflate the view
edittext = (EditText) view.findViewById(R.id.myEditText);
edittext.addTextWatcher(new TextWatcher() {
// Any callback works, but i'd go for this one
public void afterTextChanged(/*params*/) {
if(listener != null) listener.onFragment1EditTextChanged(edittext.getText().toString());
}
});
}
#Override
public void onAttach(Activity activity) {
listener = (FragmentInterface1) activity;
}
public interface FragmentInterface1 {
public void onFragment1EditTextChanged(String string);
}

Android view comparing two views for equality

I have 4 buttons on a layout, and for each of the buttons, they have the attribute:
android:onClick="numberChosen"
now, what I had planned on doing was that in my activity (which uses a layout that has the 4 buttons), I have something like:
public class Blah extends Activity{
String fileName;
Button one;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_number_players_selection_screen);
one = (Button) findViewById(R.id.number_players_one);
}
public void numberChosen(View v){
if(v == one){ // <-------- first way
System.out.println("first way");
}
if(v.getId()==R.id.number_players_one){ // <-------- second way
System.out.println("second way");
}
}
}
if you take note of what happens in the method numberChosen, between these two ways, which one is better? or are they both exactly doing the same thing?
on a side note, is doing android:onClick="numberChosen" any better or worse than just setting the View.onClickListener instead?
From my point of view, both ways are correct, they get the job done.
From performance point view, the second way might be better.
In addition, like some suggested, using the switch case might not be possible if you are using ADT 14 or higher, in a library project, because the IDs are not final (constants), so you have to use if statements in that case only.
I am using min SDK 14 and this solution is not working in some cases (work only for first row of my list adapter)
findViewById(R.id.item_icon_favourite) == view
solved by comparing with IDs
R.id.item_icon_favourite == view.getId()
public class Blah extends Activity implements OnClickListener{
String fileName;
Button one;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_number_players_selection_screen);
one = (Button) findViewById(R.id.number_players_one);
one..setOnClickListener(this); // way 1 to do that
// more better way would be customized for whole app
**one..setOnClickListener(new MyClickListener());**
}
/** The click event observer pattern for the different items on the view
*
* #see android.view.View.OnClickListener#onClick(android.view.View)
*/
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.number_players_one:
// best way 1
break;
default :
break;
}
}
}
A more custom implementation you can have a customized listener for different sections in the app as :
public class MyClickListener implements OnClickListener {
private Context mContext;
#Override
public void onClick(View v) {
mContext = v.getContext();
switch (v.getId()) {
case R.id.number_players_one:
// best way 2 and more better among all
break;
default:
break;
}
}
}
I suggest you to use switch case its more readable.Its does n't matter weather your are using android:onClick="numberChosen" or View.onClickListener()

Android - PagerAdapter not saving RadioButton's state

I have a very peculiar problem. I understand that while in the foreground the member variables of an Activity remain untouched (don't need saving to persist). Now, I have a PagerAdapter that represents a quiz with a question and three answers. I've made various objects to represent the question and answers.
A Question always has a list of exactly 3 Answer's. This is how I do it: (note: some code was left out for readability)
public class QuizPagerAdapter
{
List<Question> questionList;
Context context;
public QuizPagerAdapter (List<Question> list, Context ctx) {
questionList = list;
context = ctx;
}
#Override
public Object instantiateItem (View pager, int position) {
// Create various views (ScrollView, LinearLayout, etc)
final Question q = questionList.get(position);
RadioGroup group = new RadioGroup(context);
for (int i = 0; i < 3; i++) {
Answer a = q.getAnswer(i);
RadioButton rb = new RadioButton(context);
rb.setId(i);
rb.setText(a.getText());
rb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
RadioButton btn = (RadioButton) v;
q.unselectAll(); // unselects all Answer's
q.getAnswer(btn.getId()).setSelected(true);
}
});
if (a.isSelected()) rb.setChecked(true);
}
return view;
}
}
When I use this in my Activity, I get a nice list of Questions with three Answers. Now, when I select one Answer, the RadioButton is checked. OK, now, I scroll to the next Question and check that one, then go back to the previous Question and there the answer I checked in the first place is now not checked.
Now, this doesn't always happen, it happens sometimes, but that sometimes is enough that it can cause a problem. The Activity is never placed in the background.
I understand that Android will destroy Views in the PagerAdapter to conserve memory, thus destroying the RadioButton, this is why I have this snippet:
if (a.isSelected()) rb.setChecked(true);
But it is still happening. I've tried logging everything, debugging but I cant seem to get to the source of the problem. Maybe someone here has come across a similar problem.
Any help is appreciated,
Thank you in advance!
In the OnClick event, make sure that your reference to Question is the correct object. You might want to reference the question by the list index, because if you have two Questions on the screen at the same time, the reference of q could be the second question, but you have clicked the first questions answer.
** Added **
The issue is that q is a reference to a question, and each time through the instantiateItem function, this reference is set to a new instance of a question from the list. So when you execute the OnClick event, the value q might be pointing to the incorrect instance of question than what you expect. You would be better off getting the question out of the original list by the views index in the activity.
Something like the following:
public void onClick(View v) {
RadioButton btn = (RadioButton) v;
Question question = questionList.get(position);
question.unselectAll(); // unselects all Answer's
question.getAnswer(btn.getId()).setSelected(true);
}

Unable to setContentView with my tabhost with nested activities

My code below is based on this: http://web.archive.org/web/20100816175634/http://blog.henriklarsentoft.com/2010/07/android-tabactivity-nested-activities/
My issue is with the history ArrayList that is supposed to store the activities so I can properly utilize the back button, however my app crashes when I hit back. I think it's because history isn't exactly storing Views.
I added:
View view = getLocalActivityManager().startActivity("ViewPagerActivity", new
Intent(this,ViewPagerActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
.getDecorView();
to my back method to see if it would load it and it works.
public class FeaturedTabGroup extends ActivityGroup {
// Keep this in a static variable to make it accessible for all the nesten activities, lets them manipulate the view
public static FeaturedTabGroup group;
// Need to keep track of the history if you want the back-button to work properly, don't use this if your activities requires a lot of memory.
private ArrayList history;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.history = new ArrayList();
group = this;
// Start the root activity withing the group and get its view
View view = getLocalActivityManager().startActivity("ViewPagerActivity", new
Intent(this,ViewPagerActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
.getDecorView();
// Replace the view of this ActivityGroup
replaceView(view);
}
public void replaceView(View v) {
// Adds the old one to history
history.add(v);
// Changes this Groups View to the new View.
setContentView(v);
System.out.println("view set successful");
}
public void back() {
if(history.size() > 0) {
history.remove(history.size()-1);
setContentView((Integer) history.get(history.size()-1));
}else {
finish();
}
}
#Override
public void onBackPressed() {
FeaturedTabGroup.group.back();
return;
}
}
EDIT:
For brevity, I'll approach this problem with another question: why does setContentView(v) work, but not when the Views are store in an ArrayList? What happens to the view when it is stored in an arraylist?
Can't you work around this issue with ViewSwitcher (http://developer.android.com/reference/android/widget/ViewSwitcher.html)? It provides a cleaner solution and you could always call showPrevious() and showNext() when needed.
setContentView(int) expects a layout resource ID. In your example, can you try to save the view object itself (i.e. without type cast to integer)? As jcXavier says - viewswitcher is a better way to handle this.
Maybe it's late , but here: (history.size() > 0), change 0 to 1, when size is 1, it should just finish.
Adam,
I know it must be late... but perhaps I can help somebody else.
Here is how I solved the problem:
public void back() {
View v;
if(history.size() > 1) {
history.remove(history.size()-1);
v = (View) history.get(history.size()-1);
FirstGroup.group.setContentView(v);
}else {
finish();
}
}

Categories

Resources