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
}
});
Related
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've got a bunch of list items in my RecyclerView. I am handling the clicks properly for each item, but I need to close the activity when any item is clicked. Becuase RecyclerView doesn't have setOnItemClickListener method, I have to do this within the adapter:
#Override
public void onBindViewHolder(final Holder holder, int position) {
// ...
holder.flagNameTextView.setText(arrayList.get(position).getName());
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Go back to the previous activity
// such as onBackPressed();
}
});
}
But of course, the adapter is not extending the Activity, so I can't use onBackPressed() or finish().
How can I do this?
Use the Following:
Declare context globally.
Context c;
Then type-cast context with your activity.
((YourActivity)c).finish();
Hope this helps.
You can pass a reference of your activity throw the adapter constructor and call Activity.finish();
Hope this Helps.
Sorry for my english.
You can get the context from the flagNameTextView :
((Activity)holder.flagNameTextView.getContext()).finish();
Besides, you can define a interface callback like OnClickListener in RecyclerView adapter. Then Implement this interface in Activity, pass it into the adapter and then use it in View's OnClickListner callback.
Just use YourActivityName.this.finish().
By adding the Activity name you are telling android which "this" you want.
This will only work if your adapter is NOT defined as a static class.
I have a graph in main activity also I have a recycler view in main activity. Custom adapter is used for recyclerview. I have a check box and swipe layout in list item layout. in swipe layout there is a delete button.
I want to reset the graph of main activity when I check the check box or when I delete any item.
For this I created one method in main activity. And called this method in adapter onCheckedChangeListener and on click of delete.
But I am getting a null pointer exception on mBarChart. i.e . graph. I have instantiated in mBarChart in setUI method and this is called in onCreate of an activity.
resetMethod
public void resetGraph(Context context)
{
mBarChart.invalidate();
}
in adapter :
Context conext;
MainActivity mainActivity;
mainActivity = new MainActivity();
mainActivity.resetGraph(conext);
How to do this? Please help.. Thank you..
In Adapter call your resetMethod this way
((MainActivity)context).resetGraph(context);
Create a interface that implement Activity, Main activity in your case and override method and perform operation.
//Interface
public interface OnRefreshViewListner{
public void refreshView();
}
//Main Activity
MainActivity extends Activity implements OnRefreshViewListner
{
//Other methods
#Override
public void refreshView(){
// write refresh code here
}
}
//Initialize Interface in adapter constructor
public class YourAdapter extends BaseAdapter {
private OnRefreshViewListner mRefreshListner;
public YourAdapter (Context context) {
mRefreshListner = (OnRefreshViewListner)context;
}
//call MainActivity method
mRefreshListner.refreshView();
}
In the adapter, you should not create a new instance of MainActivity and call resetGraph(). You should use the instance of MainActivity, that created the adapter. Send the instance of MainActivity to the adapter, new Adapter(this) and save it in adapter.
You can change a view from the context of an adapter like this :
cast context to activity.
use findviewbyid method to find the view you want.
initiliaze it to a variable.
View v = ((Activity)getContext()).findViewById(WHATEVER_VIEW_COMPONENT_YOU_WANT);
change the variable as you want.
note. Don't forget to use the type of view that you want and cast the findview method to it.
If you want to call a method just cast the context to MainActivity and call it.
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);
}
DogActivity is using a custom View. The custom view handles some logic and so has fields. When a particular field reaches a certain value, I want to start a fragment whose parent is DogActivity. How would I do that?
Is it advisable to put a callback inside a custom view so that it calls its parent activity? Or is there a simpler way?
When programming you should always look for consistency, i.e. look around you and see how similar stuff to what you want to do is done. The Android SDK makes heavy use of callback listeners, so they are the way to go here.
In fact we don't even need to know what kind of View your CustomView really is, we can build a general purpose solution. Don't forget to adapt/optimize according to your specific surroundings however. And think about abstraction and generalisation once you get to a point where all your Views are spammed with listeners!
You will need 3 things:
A listener interface
public interface OnCountReachedListener {
public void onCountReached();
}
A place to accept the listener and a place to alert the listener in your CustomView
public class CustomView extends View {
private int theCount;
private OnCountReachedListener mListener;
public void setOnCountReachedListener(OnCountReachedListener listener) {
mListener = listener;
}
private void doSomething() {
while (theCount < 100) {
theCount++;
}
// The count is where we want it, alert the listener!
if (mListener != null) {
mListener.onCountReached();
}
}
An implementation of the interface in your Activity
public class DogActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
View myView = new CustomView();
myView.setOnCountReachedListener(new OnCountReachedListener() {
#Override
public void onCountReached() {
Log.w("tag", "COUNT REACHED!");
// START YOUR FRAGMENT TRANSACTION HERE
}
});
}
}
For further information look at the source code of the View class and all the On**XY**Listener interfaces in the Android SDK. They should give you plenty to think about
What is the type of the field? Is it an EditText? SeekBar? Depending on the View, you'll be able to specify different listeners/callbacks to determine when they have changed and if they've reached a certain threshold. I would attach these listeners within onCreate of DogActivity. When the threshold is reached, use a FragmentTransaction to add your Fragment as the child of a container View in DogActivity.