Android期末复习4-2:使用上下文菜单ContextMenu(长按弹出型菜单)

发布时间 2023-11-17 15:01:33作者: WINTER1208

题目

在该应用中,活动页面视图根节点为垂直的LinearLayout,在布局中依次有1个TextView,显示个人信息;1个ListView,显示字符串数据。长按ListView,则弹出ContextMenu,有两个菜单项“插入”和“删除”。选择“插入”菜单项,则在长按的位置插入1项随机整型数据,并且更新ListView;选择“删除”菜单项,则将长按位置对应的数据项删除,并且更新ListView。

实现效果

步骤

1.新建项目,更改布局文件为my_main.xml

删除app/re/layout/activity_main.xml文件,新建自己的my_main.xml布局文件,其中Root Element设置为LinearLayout,改MainActivity.java中的setContentView(R.layout.my_main)

2.对my_main.xml操作

拖入1个TextView,1个ListView,设置ListView的id为listView,删除TextView的id

代码展示

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="周冬玲21211870234" />

    <ListView
        android:id="@+id/ListView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

3.新建菜单

项目模版默认是没有菜单项的,需要手动创建,右键点击项目列表中的res->New->Android Resource File,设置文件名,Resource Type设置为Menu,点击OK即可

这里演示的是Context Menu,文件名就叫ctx_menu吧

4.对ctx_menu.xml操作

代码展示

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/ctx_insert"
        android:title="插入" />
    <item
        android:id="@+id/ctx_delete"
        android:title="删除" />
</menu>

5.MainActivity.java部分

手把手教写代码,5步解决,不懂的地方都有注释

package com.example.zdl_task4_2;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.Random;
//1.使用上下文菜单
//2.上下文菜单的创建和点击响应方法
//3.获取上下文菜单触发位置
//4.适配器数据的更新
public class MainActivity extends AppCompatActivity {

    //1.列表与适配器的声明,作为成员变量供类中的任何方法调用
    ArrayList<String> list=new ArrayList<>();//用来存放ListVIew的Item内容
    // String是泛型参数,扩大了方法接受的参数类型,如果类型不一致,取数不用强制类型转换
    ArrayAdapter<String> adapter;//将数组或列表等批量的数据转换成相同格式的批量视图,常用于Spinner、ListView、GridView等组件

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

        //2.初始化列表项,将列表项转化为批量视图
        for(int i=0;i<20;i++){//生成20个字符串添加到列表项中
            String s=String.format("Item%02d",i);//%02d,2位整数,不足两位前面补0
            list.add(s);
        }
        ListView lv=findViewById(R.id.ListView);//找ListView的id
        adapter=new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,list);//创建适配器对象
        //适配器ArrayAdapter有两个常用的构造方法:
        //(1)public ArrayAdapter(Context context,@LayoutRes int resource,T[] objects)
        //(2)public ArrayAdapter(Context context,@LayoutRes int resource,List<T> objects)
            //context:上下文,Activity对象,在MainActivity类里指MainActivity.this
            //resource:样式参数,常用android.R.layout.simple_list_item_1
            //objects:类型为数组T[]或者列表List<T>,T是泛型
        lv.setAdapter(adapter);//给ListView设置适配器

        //3.注册上下文菜单,ConTextMenu依赖于内容,需要注册才能被使用,长按被注册的视图,才能弹出上下文菜单,若不注册,不会生成菜单
        registerForContextMenu(lv);
    }
    //4.重写上下文菜单onCreateContextMenu,每次弹出上下文菜单都会被调用,ContextMenu重要方法1
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);

        // 将res/menu/ctx_menu.xml菜单文件填充到menu对象上
        // 方法1:获得菜单填充器get方法,再调用其inflate填充方法
        getMenuInflater().inflate(R.menu.ctx_menu,menu);

        // 方法2:创建菜单填充器对象,传入getApplicationContext方法获得应用上下文,后调用inflate填充方法
        //new MenuInflater(getApplicationContext()).inflate(R.menu.ctx_menu,menu);
    }

    //5.重写菜单点击事件方法onContextItemSelected,处理菜单点击后一系列操作,ContextMenu重要方法2
    //若是针对ListView、GridView等组件,需要知道弹出上下文菜单的位置
    @Override
    public boolean onContextItemSelected(@NonNull MenuItem item) {
        // 获取弹出上下文菜单的位置
        // item.getMenuInfo方法得到的ConTextMenuInfo对象无法获取position或者id信息
        // 需要先将ContextMenuInfo对象强制类型转换成AdapterContextMenuInfo对象,再调用position信息
        //只记住等号后面怎么写就行,前面可以用ctrl+alt+v生成
        ContextMenu.ContextMenuInfo menuInfo = item.getMenuInfo();//通过item.getMenuInfo方法得到ConTextMenuInfo对象
        AdapterView.AdapterContextMenuInfo adapterContextMenuInfo= (AdapterView.AdapterContextMenuInfo) menuInfo;//强制类型转换
        int position=adapterContextMenuInfo.position;//获取position信息

        int position1 = ((AdapterView.AdapterContextMenuInfo) item.getMenuInfo()).position;
        switch (item.getItemId()){
            //实现插入菜单的功能:将数据添加到list对应位置中,然后更新适配器视图
            case R.id.ctx_insert:
                String s=String.format("Item%04d",new Random().nextInt(10000));
                list.add(position,s);
                adapter.notifyDataSetChanged();//更新适配器视图,一旦数据源数据发生变化,就需要调用适配器更新视图,保持视图与数据一致
                break;
            //实现删除菜单的功能:将数据从list中删除,然后更新适配器视图
            case R.id.ctx_delete:
                list.remove(position);
                adapter.notifyDataSetChanged();
                break;
        }
        return super.onContextItemSelected(item);//自动生成的,不需要记忆
    }
}

重点总结

本题重难点在MainActivity.java代码的编写上,下面总结了代码编写的思路,方便复习

第一步:列表与适配器的声明,作为成员变量供类中任何方法使用

第二步:初始化列表项

生成n个字符串添加到列表项中

->找ListVIew的id(findViewById),变量名设置为lv

->构造适配器(new ArrayAdapter<>( , ,);ctrl+alt+v)

->将适配器添加到ListView中(lv.setAdapter)

第三步:为ListView注册上下文菜单

registerForContextMenu(lv)

第四步:重写上下文菜单方法onCreateContextMenu(在onCreate方法外)

将res/menu/ctx_menu.xml菜单文件填充到menu对象上,两种方法,我较喜欢用第一种,即在自动生成的代码中加入getMenuInflater().inflate(R.menu.ctx_menu,menu)

第五步:重写菜单点击事件方法onContextItemSelected

获取菜单点击的位置((AdapterView.AdapterContextMenuInfo) item.getMenuInfo()).position;ctrl+alt+v

->实现插入菜单的功能(将数据添加到list对应为止中,更新适配器视图adapter.notifyDataSetChanged();)

->实现删除菜单的功能(将数据从list中删除,更新适配器视图)

接下来放几张老师的PPT,总结一下更细节的知识点

 注:所学内容出自https://space.bilibili.com/549342748/channel/seriesdetail?sid=3616542