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);
}
Related
I have one activity which is hosting several tabs(Fragment), now I want to get EditText by id from tab(Fragment) to its hosting activity and set listener on it.
So please help me to get rid of it.
Thanks in advance
To find view by id from fragment, add this:
EditText edittext = getActivity().findViewById(R.id.edittext);
The simple solution is
EditText editText = (EditText)getActivity().findViewById(R.id.viewid);
if( editText != null){
// set listener here
}
In your Activity
public EditText editText;
if(editText != null)
editText.setOnClickListner(this);
In your Fragment
Activity activity = (Activity)context;
//where context is your fragment's context
activity.edtText = (EditText)findViewById(R.id.viewid);
Make sure you set listener when editText is not null otherwise you will get null pointer exeption.
There can be multiple solutions to this. In my opinion the best way is to make an interface named Callback as below
public interface Callback
{
public void onListenerActionPerformed(Some args);
}
Now in whatever fragment you want the listener to be attached, write a function
private Callback callback;
public void setCallback(Callback callback)
{
this.callback=callback;
}
Now register the listener on your EditText in the fragment and inside the body of the corresponding function write
callback.onListenerActionPerformed(Some parameter)
Now from your activity, right below where you have instantiated the fragment write,
fragmentInstanceName.setCallback(new Callback(){
public void onListenerActionPerformed(Some args){
//Your implementation
}
});
There is an Activity that displays listItems (through a cursorAdapter).
The listItem's XML contains some buttons. In the Cursor Adapter's newView() method, these buttons get the onClickListener, not by an anonymous declaration, there's a class that implements the listener. If there's a click on a certain button, the activity where all that happens, should finish.
I'm not surprised that calling finish() in the button class doesn't work. activityContext.finish doesn't work either.
So how can I manage that?
public class DetailActvityActionBtn implements View.OnClickListener {
private Context context;
#Override
public void onClick(View view){
context = view.getContext();
System.out.println("CONTEXT:" + context);
///Itemroot
LinearLayout root =(LinearLayout) view.getRootView().findViewById(R.id.detailRoot);
///Tag that stores data
ItemViewAndDataHolder holder = (ItemViewAndDataHolder) root.getTag();
System.out.println("HOLDER: " + holder.toString());
//Get id of item
int id = holder.getId();
//Get quantity of item
int quantity = Integer.parseInt(holder.getQuantity().getText().toString().replaceAll("[^0-9]",""));
///Append id to URI
Uri updateItemUri = ContentUris.withAppendedId(InventoryDB_Contract.entries.CONTENT_URI, id);
///To determine the clicked button, get ID as String
String btnIDasString = context.getResources().getResourceName(view.getId());
System.out.println(btnIDasString);
ContentValues values = new ContentValues();
int updatedRow;
switch (btnIDasString){
case "com.example.android.inventoryapp:id/plusBtn":
System.out.println("plus");
values.put(InventoryDB_Contract.entries.COLUMN_PRODUCT_QUANTITY_IN_STOCK, quantity + 1);
context.getContentResolver().update(updateItemUri, values, null, null);
//CRcaller.saleItem(1);
break;
case "com.example.android.inventoryapp:id/minusBtn":
System.out.println("mins");
values.put(InventoryDB_Contract.entries.COLUMN_PRODUCT_QUANTITY_IN_STOCK, quantity - 1);
updatedRow = context.getContentResolver().update(updateItemUri, values, null, null);
break;
case "com.example.android.inventoryapp:id/deleteItemBtn":
System.out.println("delete");
context.getContentResolver().delete(updateItemUri, null, null);
context.finish();
break;
}
}
}
Typecast your activity context into an activity. And then call finish method
Activity act=(Activity)context;
act.finish();
public class DetailActvityActionBtn implements View.OnClickListener
You are not extending Activity or Fragment or anything along those lines, you have no context to execute context.finish(); from because finish() is a method from Activity.
If this class is utilized from an Activity then pass in that activity's reference to the class constructor, like so:
public MainActivity extends Activity{
//You standard onCreate() blah...
DetailActvityActionBtn yourHandlerClass = new DetailActvityActionBtn(this);
}
public class DetailActvityActionBtn implements View.OnClickListener {
private Activity activity;
public DetailActvityActionBtn(Activity activity){
this.activity = activity;
}
#Override
public void onClick(View view){
//You can now call activity.finish() to close the calling activity...
activity.finish();
}
Personally, I would suggest decoupling the button's reliance upon the existence of an activity. Rather than setting the functionality of onClick within the Button class, why not define the functionality within your controller (Activity)? You can define one onClick method and use your listview logic to determine which buttons should have this functionality.
If you were simply controlling business logic that would be one thing, but I personally think it's convoluted to have the view define the controller life cycle. The controller can give permission to the button to dismiss itself, but any other way and the button starts talking to things it probably shouldn't. Maybe you're following a different paradigm than MVC, so I could be wrong!
I was thinking something along the lines of:
#Override
public View getView(int position, View v, ViewGroup parent) {
if(condition1){
v.button.setOnClickListener(locallyDefinedOnClickForCondition1);
}
else if(condition2){
v.button.setOnClickListener(locallyDefinedOnClickForCondition2);
}
}
Would definitely not say it's the best solution, but maybe this could put you in the right direction. Anyone have any criticism?
I have a ListView which is in a Fragment. Each row display a set of 4 buttons.
Each button has an OnClickListener defined in the Adapter Class. Everything is working well and i can diplay the ID of the clicked button.
My problem is how the send this ID to the activity (who hold the Fragment where the ListView is defined) via this Fragment. I'm stuck since 1 week till now !!!
Please remember that this activity is already existing and she is the one who already launched the fragment.
Write one method in the Activity class,
public void setButtonClick(int buttonId){
// do your task
}
and from your adapter class
((YourActivity)fragment.getActivity()).setButtonClick(id);
But you need to pass fragment instance to the adapter using its constructor.
New Edits as per your code posted here,
class ArticleSetAdapter{
// Variables
private ArticleFragment context;
// Constructor
public ArticleSetAdapter(ArticleFragment context, ArrayList<ArrayList<Article>> articleSetArray) {
super(context.getActivity(), 0, articleSetArray);
this.context = context;
}
and in your adapter onClick,
// the OnClickListener handler method
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Integer artID = (Integer) ((Button) v).getTag();
((youractivity.class)context.getActivity())..setButtonClick(artID)
makeText(getContext(), "CLICK: " + artID, Toast.LENGTH_SHORT).show();
}
};
Hope this will help you.
I have two Activities. Activity 1 is designed to take in user input (EditText), and has a button that (if clicked) will go to activity 2. In activity 2, there is a LinearLayout and a button that will take you back to activity 1. I can currently add one textView (containing the user input from activity 1) to the LinearLayout in activity 2, but I would like to add several textView objects to the LinearLayout. When I try to add user input any time after the first, it simply replaces the textView object that held the information from the user input that was entered the first time.
From Activity 1 (AddExercise):
public class AddExercise extends AppCompatActivity {
private EditText name;
private EditText weight;
private EditText sets;
private EditText reps;
private String deets;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_exercise);
Button button = (Button) findViewById(R.id.button5);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
goToAddWorkout();
}
});
}
private void goToAddWorkout() {
Intent intent = new Intent(this, AddWorkout.class);
name = (EditText) findViewById(R.id.name);
weight = (EditText) findViewById(R.id.weight);
sets = (EditText) findViewById(R.id.sets);
reps = (EditText) findViewById(R.id.reps);
deets = name.getText().toString() + "\n\t\tWeight: " + weight.getText().toString() + "\n\t\tSets: " + sets.getText().toString() + "\n\t\tReps: " + reps.getText().toString();
intent.putExtra("details", deets);
startActivity(intent);
}
}
From Activity 2 (AddWorkout):
public class AddWorkout extends AppCompactActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_workout);
LinearLayout vBox = (LinearLayout) findViewById(R.id.vBox);
Bundle extras = getIntent().getExtras();
if (extras != null) {
TextView tv = new TextView(this);
tv.setText(extras.getString("details").toString());
vBox.addView(tv);
}
Button button = (Button) findViewById(R.id.button3);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
goToAddExercise();
}
});
}
}
You can try a public static List of String each time you can add your text to list and then On your second activity create text-view as per your list count. And add to your linear-layout.
For more click here....
So you want to be able to add multiple entries in your second activity, for every time you add one in the first. I would recommend a different and easier approach.
In your second activity, use a listview/recyclerview, instead of adding new textview. This has the added advantage that once you have added enough entries, scrolling won't be an issue.
Maintain a global list of entries, which you add the entries to. And populate the listview using this list.
you should try something like that as said by roshan-
((ArrayAdapter)listView.getAdapter()).insert(data_object, index);
((ArrayAdapter)listView.getAdapter()).notifyDataSetChanged();
use a shared preference for index... every time you come to second activity increment the index... on exit of app just clear the shared pref index variable.
Also you can add textview in your each list view item
There can be several ways to do it according to me, pick the one that suits your relevant application.
have a single activity and host two fragments. So you can share the data between the fragments using single activity. (Recommended way, I guess Fragments will ease the job for you.). Also you can store a local variable in Activity so that each time you start your application you can start it afresh, if its intended!
If not, you can use SharedPreferences. For each button click, add a string to the preference. When you add one more click, append the new data with a separator like ("|", "||").. So in Activity one write to the preference, in activity 2 read from the preference and display it as list view of dynamically create the linear layout and append it to the root layout.
Declare a static ArrayList in your Activity 1 and access it in activity 2. (Really bad way)
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.