题目
在该应用中,活动页面视图根节点为垂直的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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通