Search code examples
javaandroidonconfigurationchanged

How to get the counter value that is initiated in a method


I'm building an app that dynamically generates Buttons. Saving the buttons through onSaveInstanceState does not work since I can't save UI elements through that so the option that makes the most sense is to recreate the views per orientation change. I know exactly how to do that (overriding the onConfigurationChanged method) but my problem is that I'm not able to get the current counter value. The counter variable is global but its not initiated. It increments inside the onFloatActionButtonClick to keep a check on how many buttons I've added but I can't access that inner value from onConfigurationChanged method to recreate the same amount of buttons that were destroyed through the orientation change.

All help is appreciated.

public class MainActivity extends AppCompatActivity {

    int counter = 0;

    FloatingActionButton addingSemester;
    Button semesterButton;
    LinearLayout semesterLayout;
    GridLayout semesterGridLayout;

    LinearLayout.LayoutParams portraitLayoutParams = new LinearLayout.LayoutParams(
            AppBarLayout.LayoutParams.MATCH_PARENT,
            AppBarLayout.LayoutParams.WRAP_CONTENT);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        addingSemester = (FloatingActionButton) findViewById(R.id.addActionButton);
        semesterLayout = (LinearLayout) findViewById(R.id.main_layout);

        semesterGridLayout = (GridLayout)findViewById(R.id.semester_grid_layout);

        semesterButton = new Button(MainActivity.this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

            if (id == R.id.delete) {
                new AlertDialog.Builder(MainActivity.this)
                        .setTitle("Delete entry")
                        .setMessage("Are you sure you want to delete everything?")
                        .setCancelable(true)
                        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                if (MainActivity.this.getResources().getBoolean(R.bool.is_landscape)) {
                                    semesterGridLayout.removeAllViews();
                                } else if (!MainActivity.this.getResources().getBoolean(R.bool.is_landscape)) {
                                    semesterLayout.removeAllViews();
                                }
                                counter = 0;
                            }
                        })
                        .setNegativeButton("No", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.cancel();
                            }
                        })
                        .show();
                return true;
            }


        return super.onOptionsItemSelected(item);

    }

    public void onFloatActionButtonClick(View view) {
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);

        double width = (size.x)/3;

        semesterButton = new Button(MainActivity.this);
        if (counter < 8) {
            semesterButton.setId(counter + 1);
            semesterButton.setText("Semester " + (counter + 1));
            semesterButton.setBackgroundColor(getColor(R.color.colorPrimary));
            semesterButton.setTextColor(Color.WHITE);
            portraitLayoutParams.setMargins(24, 24, 24, 24); // keep this line

            if (MainActivity.this.getResources().getBoolean(R.bool.is_landscape)) {
                GridLayout.LayoutParams params = new GridLayout.LayoutParams();
                params.setMargins(24, 24, 24, 24);
                params.width = (int) width;
                params.height = GridLayout.LayoutParams.WRAP_CONTENT;
                semesterButton.setLayoutParams(params);
                semesterGridLayout.addView(semesterButton);
            } else if (!MainActivity.this.getResources().getBoolean(R.bool.is_landscape)) {
                semesterLayout.addView(semesterButton);
                semesterButton.setLayoutParams(portraitLayoutParams); // keep this line
            }

            counter++;
            setOnLongClickListenerForSemesterButton();

        } else if (counter == 8) {
            Toast.makeText(MainActivity.this, "You cannot add more than 8 semesters", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);


        if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            Toast.makeText(MainActivity.this,"Screen is in Orientation", Toast.LENGTH_SHORT).show();
        }
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            Toast.makeText(MainActivity.this, "Screen is in Landscape", Toast.LENGTH_SHORT).show();
        }
    }

    private void setOnLongClickListenerForSemesterButton() {
        semesterButton.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                final Button b = (Button) v;
                b.setTag(b.getText().toString());
                b.setBackgroundColor(Color.RED);
                b.setText("Delete");

                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                        builder.setTitle("Delete entry");
                        builder.setMessage("Are you sure you want to delete this entry?");
                        builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                if (MainActivity.this.getResources().getBoolean(R.bool.is_landscape)) {
                                    semesterGridLayout.removeView(b);
                                    for (int i = 0; i < semesterGridLayout.getChildCount(); i++) {
                                        ((Button) semesterGridLayout.getChildAt(i)).setText("Semester " + (i + 1));
                                    }
                                } else if (!MainActivity.this.getResources().getBoolean(R.bool.is_landscape)) {
                                    semesterLayout.removeView(b);
                                    for (int i = 0; i < semesterLayout.getChildCount(); i++) {
                                        ((Button) semesterLayout.getChildAt(i)).setText("Semester " + (i + 1));
                                    }
                                }
                                counter--;
                            }
                        });
                        builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                b.cancelLongPress();
                                b.setBackgroundColor(ContextCompat.getColor(MainActivity.this, R.color.colorPrimary));
                                b.setText(b.getTag().toString());
                                dialog.cancel();

                            }
                        });
                        builder.show();
                return true;
            }
        });
    }
}

EDIT

This is where I'm trying to hide my MenuItem when there are no views.

@Override
    public boolean onOptionsItemSelected(MenuItem item) {

        Configuration newConfig = new Configuration();

        if(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
            if(semesterLayout.getChildCount() == 0){
                item.setVisible(false);
            }
        }

        if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
            if (semesterGridLayout.getChildCount() == 0){
                item.setVisible(false);
            }
        }

        int id = item.getItemId();

            if (id == R.id.delete) {
                new AlertDialog.Builder(MainActivity.this)
                        .setTitle("Delete entry")
                        .setMessage("Are you sure you want to delete everything?")
                        .setCancelable(true)
                        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                if (MainActivity.this.getResources().getBoolean(R.bool.is_landscape)) {
                                    semesterGridLayout.removeAllViews();
                                } else if (!MainActivity.this.getResources().getBoolean(R.bool.is_landscape)) {
                                    semesterLayout.removeAllViews();
                                }
                                counter = 0;
                            }
                        })
                        .setNegativeButton("No", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.cancel();
                            }
                        })
                        .show();
                return true;
            }


        return super.onOptionsItemSelected(item);

    }

Solution

  • If onConfigurationChanged() is called then the activity will not be restarted by Android and you don't need to save the instance of the activity to restore it. But be careful, from the documentation

    Remember: When you declare your activity to handle a configuration change, you are responsible for resetting any elements for which you provide alternatives. If you declare your activity to handle the orientation change and have images that should change between landscape and portrait, you must re-assign each resource to each element during onConfigurationChanged().

    The counter variable is global so you can access it from the onConfigurationChanged() method and the value of the variable will be preserved when the screen orientation changes, because Android will not restart the activity. You can access it as you do in your onFloatActionButtonClick(...) method

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    
        System.out.println(counter); //Print the counter value
    }
    

    Using onConfigurationChanged() will preserve the activity instance and views that have been added during runtime (views add when a button is pressed for example). If you want to achieve the same result by restarting the activity, you need to save the counter value, then in your onCreate method you have to restore the counter value and repopulate the layout based on that value.

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        // Save the counter value
        savedInstanceState.putInt("counter", counter);
    
        // Always call the superclass so it can save the view hierarchy state
        super.onSaveInstanceState(savedInstanceState);
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        addingSemester = (FloatingActionButton) findViewById(R.id.addActionButton);
        semesterLayout = (LinearLayout) findViewById(R.id.main_layout);
    
        semesterGridLayout = (GridLayout)findViewById(R.id.semester_grid_layout);
    
        semesterButton = new Button(MainActivity.this);
    
        if (savedInstanceState != null) {
            // Restore the counter value
            counter = savedInstanceState.getInt("counter");
    
            //Repopulate the layout
            for(int i = 0; i < counter; i++) {
                addSemesterButton(i);
            }
        }
    }
    
    public void addSemesterButton(int id) {
        //This is an edited version of onFloatActionButtonClick(...) method
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
    
        double width = (size.x)/3;
    
        semesterButton = new Button(MainActivity.this);
        semesterButton.setId(id + 1);
        semesterButton.setText("Semester " + (id + 1));
        semesterButton.setBackgroundColor(getColor(R.color.colorPrimary));
        semesterButton.setTextColor(Color.WHITE);
        portraitLayoutParams.setMargins(24, 24, 24, 24); // keep this line
    
        if (MainActivity.this.getResources().getBoolean(R.bool.is_landscape)) {
            GridLayout.LayoutParams params = new GridLayout.LayoutParams();
            params.setMargins(24, 24, 24, 24);
            params.width = (int) width;
            params.height = GridLayout.LayoutParams.WRAP_CONTENT;
            semesterButton.setLayoutParams(params);
            semesterGridLayout.addView(semesterButton);
        } else if (!MainActivity.this.getResources().getBoolean(R.bool.is_landscape)) {
            semesterLayout.addView(semesterButton);
            semesterButton.setLayoutParams(portraitLayoutParams); // keep this line
        }
    }
    

    For more info https://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange