Question

Hi I was wondering why updating the text of a button behave different in my app.

I call a fragment that gets the information what the button should be updated with, I do a interface-callback from the fragment to update a global variable that the activity updates the button text.

The problem is that the activity where the button is located doesn't refresh the button to show the new text but if I do it through the fragment it works, invalidating the button doesn't work or force refresh if I do it through the activity.

Here is the activity that calls when you press the button who then calls a fragment who shows a list and when you click on a option the button should change its text to whatever you have choosed:

public void onClick_testSite(View view)
{
    // create the fragment
    SelectChartTypeDialogFragment chartType = new SelectChartTypeDialogFragment();
    // register you as a delegate for the callback
    chartType.delegate = this;
    // show the list
    chartType.show(getFragmentManager(), "WEE");

    // fetch the button and set the text ** DOESNT WORK **
    Button p1_button = (Button)findViewById(R.id.btn_pickChart);
    p1_button.setText(response);
    p1_button.invalidate();


}

@Override
public void processFinish(String response)
{
    this.response = response;
}

and here is part of the fragment that handles the dialog:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    // get the list from a enum
    final List<ChartTypes> chartList = Arrays.asList(ChartTypes.values());
    // The array containing the different choices
    ArrayAdapter<ChartTypes> adapter = new ArrayAdapter<ChartTypes>(
            getActivity(), android.R.layout.simple_list_item_1, chartList);
    // Use the Builder class for convenient dialog construction
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

    // The dialog setting
    builder.setTitle(R.string.pick_chart);
    builder.setAdapter(adapter, new DialogInterface.OnClickListener()
    {
        public void onClick(DialogInterface dialog, int position)
        {
            // get the name of the enum based on the position, what one
            // clicked on the dialog
            String strName = chartList.get(position).name();

            // this sets the text in the activitys global variable
            delegate.processFinish(strName);
            // set the text in the fragment instead
            //changeBtnText(strName);

            //dialog.dismiss();
        }
    });

    // Create the AlertDialog object and return it
    return builder.create();
}

public void changeBtnText(String newBtnxt)
{
    Button button = (Button)getActivity().findViewById(R.id.btn_pickChart);
    button.setText(newBtnxt);
}

My question is, why does it update the text on the gui(when running the app) through the fragment but not through the activity, i.e the method p1_button.setText(response);?

EDIT answer as explained by Raghunandan: Problem was that I didn't understand that onClick_testSite(View view) completed even if you did not click anything on the dialog, I thought it waited with the function call of chartType.show() for it to return and then proceed to the end of the function.

Was it helpful?

Solution

You need to initialize public AsyncResponse delegate = null;

delegate =(AsyncResponse) getActivity();

I believe this is the implemented method

@Override
public void processFinish(String response)
{
     Log.i(".........",response); // check if the response is logged
     // if you get the response your button text will be changed
     // else you need to look at why the response is not logged.  
     p1_button.setText(response);
}

Declare Button p1_button as instance variable ( for example before onCreate).

Initialize this

p1_button = (Button)findViewById(R.id.btn_pickChart); // in onCreate

Probably the button is refreshed even before the response is received in processFinish. Then you initialize the response variable. So the button text is set the next time you click on the button.

You can declare the button before onCreate and update it in processFinish insteadas hwon above.

OTHER TIPS

The processFinish saves the value to response. But it does not applied for TextView with btn_pickChart id.

So, you just need to save the instance of TextView for Activity:

private Button mP1Button;

protected void onCreate(Bundle savedInstanceState) {
...
    Button mP1Button = (Button) findViewById(R.id.btn_pickChart);
...
}

And apply the changed value when processFinish is called:

public void processFinish(String response) {
    this.response = response;
    // The value will be setup to the view element.
    mP1Button.setText(response);
}

For the best way do not use the delegate as field. You could use the getActivity() or getTargetFragment() to check on instanceOf AsyncResponse and call the processFinish method.

AsyncResponse asyncResponse = null;
if(getActivity() instanceof AsyncResponse) {
    asyncResponse = (AsyncResponse) getActivity();
} else if (getTargetFragment() instanceof AsyncResponse){
    asyncResponse = (AsyncResponse) getTargetFragment();
}

if(asyncResponse != null){
    asyncResponse.processFinish(strName);
}

By the way, no need to call the invalidate method after setText because it is already called from here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top