本文围绕以下三个部分展开:
一、BaseAdapter 自定义适配器
二、一个案例
附 代码补充
一、BaseAdapter 自定义适配器
它是 Android 应用程序中经常用到的基础适配器,它的主要用途是将一组数据传到 ListView、Spinner、Gallery 及 GridView 等 UI 显示组件。
二、一个案例
案例说明:
读取手机的SD卡中的目录和文件(全部读出/过滤不允许读的文件和隐藏文件),并显示成上图的样子。
目录:显示出目录(文件夹)的图标、目录名、包含几个文件。文件:显示出文件的图标、文件名、文件大小。
点击右边的按钮,出现弹出菜单,里面有“复制”和“删除”两项。分别点击,会弹出提示信息。
1. 在 styles.xml(v21) 中设置标题栏颜色。
<item name="android:colorPrimaryDark">@android:color/holo_blue_dark</item>
<item name="android:colorPrimary">@android:color/holo_blue_light</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
2. 在功能清单中授予读取SD卡的权限,这样,本APP才可以读取到手机SD卡。
<!-- 授予此App读取SD卡的权限
(注意大小写,不能写为:ANDROID.PERMISSION.READ_EXTERNAL_STORAGE)-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
3. 启动后,会先启动MainAcitivity,然后加载主活动的布局文件(主界面)。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 加载主活动的布局文件
setContentView(R.layout.activity_main);
}
因此要写主界面 activity_main.xml :列表框(ListView)。
<!-- 主活动的布局文件:列表框-->
<ListView
android:id="@+id/listView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
因为ListView里面也有布局文件,用来放图片、文件/目录名等控件,因此接下来写里面的布局文件。该布局文件中,有一些字符串,因此先在 strings.xml 中写需要的字符串。
<string name="filename">文件名</string>
<string name="summary">文件/目录 概要信息</string>
<string name="copy">复制</string>
<string name="delete">删除</string>
<string name="sd_card_error">读取SD卡出错</string>
然后再创建里面的布局文件:file_item.xml ,然后写布局。
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:src="@drawable/ic_file"
android:contentDescription="@string/filename"/>
<ImageButton
android:id="@+id/btnOperator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="@drawable/ic_more_vert_grey600_16dp"
style="@android:style/Widget.DeviceDefault.Button.Borderless.Small"/>
<TextView
android:id="@+id/tvFilename"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/imageView"
android:layout_marginLeft="18dp"
android:layout_toRightOf="@id/imageView"
android:text="@string/filename"
android:textSize="16sp"/>
<TextView
android:id="@+id/tvSummary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/tvFilename"
android:layout_alignParentBottom="true"
android:layout_alignStart="@id/tvFilename"
android:text="@string/summary"
android:textSize="12sp"/>
4. 判断SD卡状态,并读取SD卡内容。
(1)判断SD卡状态是否有效。如果有效,弹出提示“SD card is ok”;否则,弹出提示:“读取SD卡出错”。
// 获得当前设备的SD卡的状态:Environment.getExternalStorageState()
// SD卡正在使用:Environment.MEDIA_MOUNTED
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Toast.makeText(this,"SD card is ok",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, getString(R.string.sd_card_error), Toast.LENGTH_SHORT).show();
}
然后在手机上部署,显示以下效果,说明SD卡正在使用。
(2)获得SD卡的根目录下的目录/文件列表。(此处获得的,是所有的目录和文件列表)
public class MainActivity extends Activity {
private ListView listView;
private File[] files;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
// 获得当前设备的SD卡的状态:Environment.getExternalStorageState()
// SD卡正在使用:Environment.MEDIA_MOUNTED
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Toast.makeText(this,"SD card is ok",Toast.LENGTH_SHORT).show();
// 获得SD卡的根目录下的目录/文件
files = Environment.getExternalStorageDirectory().listFiles();
} else {
Toast.makeText(this, getString(R.string.sd_card_error), Toast.LENGTH_SHORT).show();
}
}
(3)先初始化根路径,然后通过创建文件过滤器,过滤不允许读的文件和隐藏文件,接着获得SD卡根目录下面允许读的文件/目录列表。
public class MainActivity extends Activity {
private ListView listView;
private File[] files;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
// 获得当前设备的SD卡的状态:Environment.getExternalStorageState()
// SD卡正在使用:Environment.MEDIA_MOUNTED
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
// 初始化根路径(/storage/emulated/0)
File sdPath = Environment.getExternalStorageDirectory();
// 创建文件过滤器(过滤不允许读的文件/隐藏文件)
SdFileFilter sdFileFilter = new SdFileFilter();
// 获得SD卡的根目录下的目录/文件(文件列表)
files = sdPath.listFiles(sdFileFilter);
} else {
Toast.makeText(this, getString(R.string.sd_card_error), Toast.LENGTH_SHORT).show();
}
}
其中,用到了SD卡文件过滤器 SdFileFilter ,因此需创建此文件过滤器。
package com.xiangdong.baseadapter;
import java.io.File;
import java.io.FileFilter;
/**
* SD Card文件过滤器
* Created by Xiangdong on 2015/6/4.
*/
public class SdFileFilter implements FileFilter {
/**
* 不允许读的文件/隐藏文件 不显示
*/
@Override
public boolean accept(File pathname) {
if (pathname.isHidden() || !pathname.canRead()) {
return false;
}
return true;
}
}
注意:以上只是获得了文件/目录列表,并放入了数组中,但并未进行填充。
5. 创建文件适配器 FileAdapter 类,继承自 BaseAdapter。然后将数据与该适配器关联,接着将布局与适配器关联。
public class MainActivity extends Activity {
private ListView listView;
private File[] files;
private FileAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File sdPath = Environment.getExternalStorageDirectory();
SdFileFilter sdFileFilter = new SdFileFilter();
files = sdPath.listFiles(sdFileFilter);
// 数据(文件列表)显示的方式:数据与适配器关联
adapter = new FileAdapter(this, files);
// 布局与适配器关联
listView.setAdapter(adapter);
} else {
Toast.makeText(this, getString(R.string.sd_card_error), Toast.LENGTH_SHORT).show();
}
}
6. 进入 FileAdapter 类,写该文件适配器。
(1)创建构造方法。
/**
* 自定义文件适配器类
* Created by Xiangdong on 2015/6/4.
*/
public class FileAdapter extends BaseAdapter {
// 上下文
private Context context;
// 数据(文件列表)
private File[] files;
// 布局填充器(加载布局文件)
private LayoutInflater inflater;
/**
* 4.1 构造方法
*
* @param context 上下文
* @param files 数据(文件列表)
*/
public FileAdapter(Context context, File[] files) {
this.context = context;
this.files = files;
inflater = LayoutInflater.from(context);
}
}
(2)继承了 BaseAdapter 类,要重写(override)四个方法。
(2.1)重写 getCount() 方法。
/**
* 获得数据的总数
*
* @return 文件列表的长度
*/
@Override
public int getCount() {
return files.length;
}
(2.2)重写 getItem(int position) 方法。
/**
* 获得特定位置的数据
*
* @param position 位置
* @return 特定位置的数据
*/
@Override
public Object getItem(int position) {
return files[position];
}
(2.3)重写 getItemId(int position) 方法。
/**
* 获得特定位置数据的 id (使用SQLite的场景)
*
* @param position 位置
* @return 特定位置数据的 id
*/
@Override
public long getItemId(int position) {
// 位置是列表项在 ListView 中的索引
// 在排序规则改变时,位置的数值会改变
// id 是数据的唯一标识,不会改变
return 0;
}
(2.4)重写 getView(int position, View convertView, ViewGroup parent) 方法。
/**
* (2.4) 获得特定位置加载了数据的视图(列表项)
*
* @param position 位置
* @param convertView 可重用的视图
* @param parent 父元素
* @return 列表项
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
ImageButtonListener listener = null;
if (convertView == null) {
// 若无【可重用的视图】,才实例化 xml 文件创建视图
// inflate 方法执行的次数为屏幕上能显示的列表项的最大值
convertView = inflater.inflate(R.layout.file_item, parent, false);
// 创建【结构持有者】,获得视图中的各个控件
holder = new ViewHolder();
holder.imageView = (ImageView) convertView.findViewById(R.id.imageView);
holder.btnOperator = (ImageButton) convertView.findViewById(R.id.btnOperator);
holder.tvFilename = (TextView) convertView.findViewById(R.id.tvFilename);
holder.tvSummary = (TextView) convertView.findViewById(R.id.tvSummary);
// 创建按钮的监听器
listener = new ImageButtonListener();
// 注册监听器
holder.btnOperator.setOnClickListener(listener);
// 将监听器存储【绑定】到按钮中
holder.btnOperator.setTag(listener);
// 将【结构持有者】存储到视图中
convertView.setTag(holder);
} else {
// 有【可重用的视图】,则从中取出它的【结构持有者】
holder = (ViewHolder) convertView.getTag();
// 获得按钮的监听器
listener = (ImageButtonListener) holder.btnOperator.getTag();
}
// 在【结构持有者】中加载 position 位置的数据
// 获得的是根据位置取出的一个,返回的是一个文件
File file = files[position];
// 进行填充
holder.tvFilename.setText(file.getName());
holder.tvSummary.setText(file.isFile()
? String.format(context.getString(R.string.fileSize), file.length())
: String.format(context.getString(R.string.contents), file.listFiles().length));
holder.imageView.setImageResource(file.isFile()
? R.drawable.ic_file
: R.drawable.ic_folder);
// 修改监听器的监听的数据
listener.setData(file);
// 返回视图
return convertView;
}
注:上面在填充的时候,需要填充 “文件大小:%,d 字节”和“目录: %d 个字节”,因此把这两个字符串也写进 strings.xml 中。
<string name="fileSize">文件大小:%,d 字节</string>
<string name="contents">目录: %d 个文件</string>
(2.4.1)列表项的【结构持有者】:ViewHolder 。
/**
* (2.4.1)列表项的 结构持有者
* 存储 file_item.xml 文件中的控件结构
* 直接通过字段访问,为提高性能
*/
private static class ViewHolder {
ImageView imageView;
ImageButton btnOperator;
TextView tvFilename;
TextView tvSummary;
}
(2.4.2)自定义的 ImageButton 点击监听器:ImageButtonListener 。
/**
* (2.4.2)FileAdapter 的内部类
* 自定义的 ImageButton 点击监听器
*/
private class ImageButtonListener implements View.OnClickListener {
// 点击时获得的数据(文件/目录)
private File data;
public void setData(File data) {
this.data = data;
}
@Override
public void onClick(View v) {
// 创建弹出菜单
PopupMenu menu = new PopupMenu(context, v);
// 加载菜单文件
menu.inflate(R.menu.popup);
// 注册菜单选项事件
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
String text = "";
switch (item.getItemId()) {
case R.id.action_copy:
// copyFile();
text = context.getString(R.string.copy);
break;
case R.id.action_delete:
// deleteFile();
text = context.getString(R.string.delete);
}
text += ": " + data.getName();
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
return true;
}
});
// 显示菜单
menu.show();
}
}
注:在 ImageButtonListener 中,这儿实现的是,在点击“复制”或“删除”后,弹出提示信息。也可以,通过调用 copyFile() 或者 deleteFile() 方法,然后通过流来实现文件/目录的复制和删除。
上面用到了弹出菜单 PopupMenu ,因此要创建弹出菜单: popup.xml。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_copy"
android:title="@string/copy"/>
<item
android:id="@+id/action_delete"
android:title="@string/delete"/>
</menu>
附 代码补充
项目目录结构如下:
(1)styles.xml(v21)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="android:Theme.Material.Light">
<item name="android:colorPrimaryDark">@android:color/holo_blue_dark</item>
<item name="android:colorPrimary">@android:color/holo_blue_light</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
</resources>
(2)AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xiangdong.baseadapter" >
<!--1. 授予此App读取SD卡的权限
(注意大小写,不能写为:ANDROID.PERMISSION.READ_EXTERNAL_STORAGE)-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
(3)strings.xml
<resources>
<string name="app_name">BaseAdapter</string>
<string name="action_settings">Settings</string>
<string name="filename">文件名</string>
<string name="summary">文件/目录 概要信息</string>
<string name="copy">复制</string>
<string name="delete">删除</string>
<string name="sd_card_error">读取SD卡出错</string>
<string name="fileSize">文件大小:%,d 字节</string>
<string name="contents">目录: %d 个文件</string>
</resources>
(4)activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<!-- 2.主活动的布局文件:列表框-->
<ListView
android:id="@+id/listView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
(5)file_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="72dp"
android:padding="@dimen/activity_horizontal_margin"
android:descendantFocusability="blocksDescendants">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:src="@drawable/ic_file"
android:contentDescription="@string/filename"/>
<ImageButton
android:id="@+id/btnOperator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="@drawable/ic_more_vert_grey600_16dp"
style="@android:style/Widget.DeviceDefault.Button.Borderless.Small"/>
<TextView
android:id="@+id/tvFilename"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/imageView"
android:layout_marginLeft="18dp"
android:layout_toRightOf="@id/imageView"
android:text="@string/filename"
android:textSize="16sp"/>
<TextView
android:id="@+id/tvSummary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/tvFilename"
android:layout_alignParentBottom="true"
android:layout_alignStart="@id/tvFilename"
android:text="@string/summary"
android:textSize="12sp"/>
</RelativeLayout>
(6)MainActivity
package com.xiangdong.baseadapter;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.Toast;
import java.io.File;
public class MainActivity extends Activity {
private ListView listView;
private File[] files;
private FileAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 2.加载主活动的布局文件
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
// 3.获得当前设备的SD卡的状态:Environment.getExternalStorageState()
// SD卡正在使用:Environment.MEDIA_MOUNTED
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
//Toast.makeText(this,"SD card is ok",Toast.LENGTH_SHORT).show();
// 获得SD卡的根目录下的目录/文件
//files = Environment.getExternalStorageDirectory().listFiles();
// 3.1 初始化根路径(/storage/emulated/0)
File sdPath = Environment.getExternalStorageDirectory();
// 3.2 创建文件过滤器(过滤不允许读的文件/隐藏文件)
SdFileFilter sdFileFilter = new SdFileFilter();
// 3.3获得SD卡的根目录下的目录/文件(文件列表)
files = sdPath.listFiles(sdFileFilter);
// 4.数据(文件列表)显示的方式:数据与适配器关联
adapter = new FileAdapter(this, files);
// 布局与适配器关联
listView.setAdapter(adapter);
} else {
Toast.makeText(this, getString(R.string.sd_card_error), Toast.LENGTH_SHORT).show();
}
}
//-------------------------------------------------------------------------------------------
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
(7)SdFileFilter
package com.xiangdong.baseadapter;
import java.io.File;
import java.io.FileFilter;
/**
* SD Card文件过滤器
* Created by Xiangdong on 2015/6/4.
*/
public class SdFileFilter implements FileFilter {
/**
* 不允许读的文件/隐藏文件 不显示
*/
@Override
public boolean accept(File pathname) {
if (pathname.isHidden() || !pathname.canRead()) {
return false;
}
return true;
}
}
(8)FileAdapter
package com.xiangdong.baseadapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
/**
* 自定义文件适配器类
* Created by Xiangdong on 2015/6/4.
*/
public class FileAdapter extends BaseAdapter {
// 上下文
private Context context;
// 数据(文件列表)
private File[] files;
// 布局填充器(加载布局文件)
private LayoutInflater inflater;
/**
* 4.1 构造方法
*
* @param context 上下文
* @param files 数据(文件列表)
*/
public FileAdapter(Context context, File[] files) {
this.context = context;
this.files = files;
inflater = LayoutInflater.from(context);
}
/**
* 4.2.1 获得数据的总数
*
* @return 文件列表的长度
*/
@Override
public int getCount() {
return files.length;
}
/**
* 4.2.2 获得特定位置的数据
*
* @param position 位置
* @return 特定位置的数据
*/
@Override
public Object getItem(int position) {
return files[position];
}
/**
* 4.2.3 获得特定位置数据的 id (使用SQLite的场景)
*
* @param position 位置
* @return 特定位置数据的 id
*/
@Override
public long getItemId(int position) {
// 位置是列表项在 ListView 中的索引
// 在排序规则改变时,位置的数值会改变
// id 是数据的唯一标识,不会改变
return 0;
}
/**
* 4.3 获得特定位置加载了数据的视图(列表项)
*
* @param position 位置
* @param convertView 可重用的视图
* @param parent 父元素
* @return 列表项
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
ImageButtonListener listener = null;
if (convertView == null) {
// 若无【可重用的视图】,才实例化 xml 文件创建视图
// inflate 方法执行的次数为屏幕上能显示的列表项的最大值
convertView = inflater.inflate(R.layout.file_item, parent, false);
// 创建【结构持有者】,获得视图中的各个控件的作用
holder = new ViewHolder();
holder.imageView = (ImageView) convertView.findViewById(R.id.imageView);
holder.btnOperator = (ImageButton) convertView.findViewById(R.id.btnOperator);
holder.tvFilename = (TextView) convertView.findViewById(R.id.tvFilename);
holder.tvSummary = (TextView) convertView.findViewById(R.id.tvSummary);
// 创建按钮的监听器
listener = new ImageButtonListener();
// 注册监听器
holder.btnOperator.setOnClickListener(listener);
// 将监听器存储【绑定】到按钮中
holder.btnOperator.setTag(listener);
// 将【结构持有者】存储到视图中
convertView.setTag(holder);
} else {
// 有【可重用的视图】,则从中取出它的【结构持有者】
holder = (ViewHolder) convertView.getTag();
// 获得按钮的监听器
listener = (ImageButtonListener) holder.btnOperator.getTag();
}
// 在【结构持有者】中加载 position 位置的数据
File file = files[position];
holder.tvFilename.setText(file.getName());
holder.tvSummary.setText(file.isFile()
? String.format(context.getString(R.string.fileSize), file.length())
: String.format(context.getString(R.string.contents), file.listFiles().length));
holder.imageView.setImageResource(file.isFile()
? R.drawable.ic_file
: R.drawable.ic_folder);
// 修改监听器的监听的数据
listener.setData(file);
// 返回视图
return convertView;
}
/**
* 4.3.1 列表项的 结构持有者
* 存储 file_item.xml 文件中的控件结构
* 直接通过字段访问,为提高性能
*/
private static class ViewHolder {
ImageView imageView;
ImageButton btnOperator;
TextView tvFilename;
TextView tvSummary;
}
/**
* 4.3.2 FileAdapter 的内部类
* 自定义的 ImageButton 点击监听器
*/
private class ImageButtonListener implements View.OnClickListener {
// 点击时获得的数据(文件/目录)
private File data;
public void setData(File data) {
this.data = data;
}
@Override
public void onClick(View v) {
// 创建弹出菜单
PopupMenu menu = new PopupMenu(context, v);
// 加载菜单文件
menu.inflate(R.menu.popup);
// 注册菜单选项事件
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
String text = "";
switch (item.getItemId()) {
case R.id.action_copy:
// copyFile();
text = context.getString(R.string.copy);
break;
case R.id.action_delete:
// deleteFile();
text = context.getString(R.string.delete);
}
text += ": " + data.getName();
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
return true;
}
});
// 显示菜单
menu.show();
}
}
}
(9)popup.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_copy"
android:title="@string/copy"/>
<item
android:id="@+id/action_delete"
android:title="@string/delete"/>
</menu>