In this lesson we will:

- create a context menu

Translated by Taras Leskiv (http://android-by-example.blogspot.com/)

 

Context menu in Android is invoked by long pressing any screen component. It is usually used in lists. When the list of similar objects is displayed (like messages in the mailbox) and you need to apply an action to one of these objects, a context menu is invoked for this object. But we didn’t study lists yet, so we will make a simpler example and will invoke a context menu for TextView.

 

Let’s create a project:

Project name: P0151_ContextMenu
Build Target: Android 2.3.3
Application name: ContextMenu
Package name: ru.startandroid.develop.contextmenu
Create Activity: MainActivity

 

Open main.xml and create two TextView objects there:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent">
	<TextView
		android:layout_height="wrap_content"
		android:textSize="26sp"
		android:layout_width="wrap_content"
		android:id="@+id/tvColor"
		android:layout_marginBottom="50dp"
		android:layout_marginTop="50dp"
		android:text="Text color">
	</TextView>
	<TextView
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:textSize="22sp"
		android:id="@+id/tvSize"
		android:text="Text size">
	</TextView>
</LinearLayout>

 

For the first TextView we will make a context menu using which we will change the text color. For the second we will change the text size.

The way of creating a context menu is quite similar to creating a simple menu. But there are some differences.

onCreateContextMenu method is invoked every time before the menu is displayed. It is passed these parameters:
- ContextMenu, into which we will add items
- View - screen element, which the context menu is invoked for
- ContextMenu.ContextMenuInfo - contains additional information, when the context menu is invoked for a list element. We don’t use it for now, but when we will learn lists, we will see that it is useful.

onContextItemSelected process method is similar to onOptionsItemSelected for a simple menu. MenuItem is passed as a parameter - it is a menu item that has been clicked.

We will also need a third method registerForContextMenu. It is passed View as a parameter and it means that context menu should be created for this View. If you do not invoke this method, context menu for a View will not be created.

 

Lets code. Open MainActivity.java. Let’s declare and find TextView and point out that context menu must be created for them.

  TextView tvColor, tvSize;
  
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        tvColor = (TextView) findViewById(R.id.tvColor);
        tvSize = (TextView) findViewById(R.id.tvSize);
        
        // context menu should be created for tvColor and tvSize
        registerForContextMenu(tvColor);
        registerForContextMenu(tvSize);
            
    }

 

Now let’s code the creation of context menus. We will use constants for storing menu item IDs.

  final int MENU_COLOR_RED = 1;
  final int MENU_COLOR_GREEN = 2;
  final int MENU_COLOR_BLUE = 3;
  
  final int MENU_SIZE_22 = 4;
  final int MENU_SIZE_26 = 5;
  final int MENU_SIZE_30 = 6;

 

And create

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
        ContextMenuInfo menuInfo) {
      // TODO Auto-generated method stub
      switch (v.getId()) {
    case R.id.tvColor:
      menu.add(0, MENU_COLOR_RED, 0, "Red");
      menu.add(0, MENU_COLOR_GREEN, 0, "Green");
      menu.add(0, MENU_COLOR_BLUE, 0, "Blue");
      break;
    case R.id.tvSize:
      menu.add(0, MENU_SIZE_22, 0, "22");
      menu.add(0, MENU_SIZE_26, 0, "26");
      menu.add(0, MENU_SIZE_30, 0, "30");
      break;
    }
    }

 

Pay attention that we define View for which context menu was invoked by its ID and depending on this ID, create a specific menu. So if context menu was invoked for tvColor, we create a menu with colors enumeration, if for tvSize - enumeration with font sizes.

We use constants as item IDs. We don’t apply grouping or sorting, that’s why we use zeros as corresponding parameters.

Now you can save everything and run. When long pressing a TextView context menu should appear.

 

But clicking on items does nothing as we haven’t written processing in onContextItemSelected method. Let’s fill it in:

    @Override
    public boolean onContextItemSelected(MenuItem item) {
      // TODO Auto-generated method stub
      switch (item.getItemId()) {
      // menu items for tvColor
    case MENU_COLOR_RED:
      tvColor.setTextColor(Color.RED);
      tvColor.setText("Text color = red");
      break;
    case MENU_COLOR_GREEN:
      tvColor.setTextColor(Color.GREEN);
      tvColor.setText("Text color = green");
      break;
    case MENU_COLOR_BLUE:
      tvColor.setTextColor(Color.BLUE);
      tvColor.setText("Text color = blue");
      break;
    // menu items for tvSize
    case MENU_SIZE_22:
      tvSize.setTextSize(22);
      tvSize.setText("Text size = 22");
      break;
    case MENU_SIZE_26:
      tvSize.setTextSize(26);
      tvSize.setText("Text size = 26");
      break;
    case MENU_SIZE_30:
      tvSize.setTextSize(30);
      tvSize.setText("Text size = 30");
      break;
      }
      return super.onContextItemSelected(item);
    }

In this method we define by ID which menu item has been clicked. And we do the corresponding actions afterwards: change the text color for tvColor and font size for tvSize. Save, run and see that context menus now react to clicks and do what is required from them

 

To broaden your horizons I would like to write something else about this topic. It may seem complicated for now, but it it’s fine. So here are some thoughts.

We have used registerForContextMenu(View view) method for turning on context menu for a specific View. This method belongs to Activity class. I’ve looked at the source code of this method. The following is written there:

  public void registerForContextMenu(View view) {
    view.setOnCreateContextMenuListener(this);
  }

 

Remember our lesson (9) about listeners and have a look at help for setOnCreateContextMenuListener (View.OnCreateContextMenuListener l) method. It looks like View uses this object as listener for creating context menu. In this case, our code is inside Activity, so it means that this object is Activity. It means when a View wants to show a context menu, it refers to listener (Activity) and it invokes its onCreateContextMenu method. So it is the similar concept as with a simple click.

 

And a line in MainActivity.java:

 registerForContextMenu(tvColor);

is absolutely equal to this line:

 tvColor.setOnCreateContextMenuListener(this);

 

 

We can also create our own object that implements View.OnCreateContextMenuListener and use it instead of Activity as a listener for creating a context menu.

Don’t forget that you can also use XML-method to create a context menu, which we have reviewed at the end of the previous lesson. Try to complete the same lesson again, but using XML-menu this time.

 

Complete lesson code:

public class MainActivity extends Activity {

  final int MENU_COLOR_RED = 1;
  final int MENU_COLOR_GREEN = 2;
  final int MENU_COLOR_BLUE = 3;

  final int MENU_SIZE_22 = 4;
  final int MENU_SIZE_26 = 5;
  final int MENU_SIZE_30 = 6;

  TextView tvColor, tvSize;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    tvColor = (TextView) findViewById(R.id.tvColor);
    tvSize = (TextView) findViewById(R.id.tvSize);

    // context menu should be created for tvColor and tvSize
    registerForContextMenu(tvColor);
    registerForContextMenu(tvSize);
  }

  @Override
  public void onCreateContextMenu(ContextMenu menu, View v,
      ContextMenuInfo menuInfo) {
    // TODO Auto-generated method stub
    switch (v.getId()) {
    case R.id.tvColor:
      menu.add(0, MENU_COLOR_RED, 0, "Red");
      menu.add(0, MENU_COLOR_GREEN, 0, "Green");
      menu.add(0, MENU_COLOR_BLUE, 0, "Blue");
      break;
    case R.id.tvSize:
      menu.add(0, MENU_SIZE_22, 0, "22");
      menu.add(0, MENU_SIZE_26, 0, "26");
      menu.add(0, MENU_SIZE_30, 0, "30");
      break;
    }
  }

  @Override
  public boolean onContextItemSelected(MenuItem item) {
    // TODO Auto-generated method stub
    switch (item.getItemId()) {
    // menu items for tvColor
    case MENU_COLOR_RED:
      tvColor.setTextColor(Color.RED);
      tvColor.setText("Text color = red");
      break;
    case MENU_COLOR_GREEN:
      tvColor.setTextColor(Color.GREEN);
      tvColor.setText("Text color = green");
      break;
    case MENU_COLOR_BLUE:
      tvColor.setTextColor(Color.BLUE);
      tvColor.setText("Text color = blue");
      break;
    // menu items for tvSize
    case MENU_SIZE_22:
      tvSize.setTextSize(22);
      tvSize.setText("Text size = 22");
      break;
    case MENU_SIZE_26:
      tvSize.setTextSize(26);
      tvSize.setText("Text size = 26");
      break;
    case MENU_SIZE_30:
      tvSize.setTextSize(30);
      tvSize.setText("Text size = 30");
      break;
    }
    return super.onContextItemSelected(item);
  }
}

 

 

In the next lesson we will:

- draw the screen programmatically, not using layout-file


Присоединяйтесь к нам в Telegram:

- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance 

- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня




Language