最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Android开发-纯按键操控文件浏览器
时间:2026-05-30 19:30:01 编辑:袖梨 来源:一聚教程网
本文分享一个教育平板项目的按键交互文件浏览器实现方案,通过纯DPAD按键操作实现本地音频资源的分层浏览功能。

- 硬件:低端 TV 盒子/,配红外遥控器,无触屏设备
- 内容:TF 卡
/听力目录下,按年级分文件夹,叶子节点是.mp3或自定义加密音频 - 核心诉求:
-
- 上下键循环选中(到顶再按上回到底部)
- 确定键进入文件夹或播放
- 返回键回到上级目录,且焦点停留在刚才进入的那个文件夹上(这是 TV 交互的硬需求)
- 文件过滤:隐藏系统目录,按年级名排序
1、定义变量
TextView title; //标题
RecyclerView recyclerView; //列表
UnitAdapter mUnitAdapter; //适配器
ArrayList> unitList; //列表数据
LinearLayout ll_no_data; //无数据view
boolean isNoData = false; //无数据标识String sDcardDir; //根目录名称
String cur_name; //当前目录名称
String cur_path; //当前目录路径
String last_title; //上次标题名称
int last_mPos = 0; //上次选择位置
int first_mPos = 0; //第一次点击位置String root_name = ""; //一级目录名称
String title_str = "";
2、初始化和加载
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_list); title_str = getIntent().getStringExtra("title"); //传入的标题
title = findViewById(R.id.title);
if (!TextUtils.isEmpty(title_str)) {
root_name = title_str;
}
title.setText(root_name);
sDcardDir = SDCardUtils.getTfStorageDirectory(this) + "/听力"; //根目录路径 recyclerView = findViewById(R.id.recyclerView);
ll_no_data = findViewById(R.id.ll_no_data);
title.setTextColor(getResources().getColor(R.color.col_1E2736));
unitList = new ArrayList<>();
mUnitAdapter = new UnitAdapter(this, new View.OnClickListener() {
@Override
public void onClick(View v) {// item点击
mUnitAdapter.mPosSomeTime = ((int) v.getTag());
Log.d("TAG", "((int) v.getTag()---> " + ((int) v.getTag()));
mUnitAdapter.notifyDataSetChanged();
ClickSelect(); //选择目录或文件
}
});
recyclerView.setAdapter(mUnitAdapter);
verifyStoragePermissions(this); //权限请求
} /**
* 获取tf卡根目录
* @param context
* @return
*/
public static String getTfStorageDirectory(Context context) {
String tfDir = null;
StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Class> smc = sm.getClass();
try {
Method getPaths = smc.getMethod("getVolumePaths", new Class[0]);
String[] paths = (String[])getPaths.invoke(sm, new Object[]{});
if (paths.length >= 2) {
tfDir = paths[1];
}
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return tfDir;
}private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE"}; //然后通过一个函数来申请
public static void verifyStoragePermissions(Activity activity) {
try {
//检测是否有写的权限
int permission = ActivityCompat.checkSelfPermission(activity,
"android.permission.WRITE_EXTERNAL_STORAGE");
if (permission != PackageManager.PERMISSION_GRANTED) {
// 没有写的权限,去申请写的权限,会弹出对话框
ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}else{
findData(sDcardDir,false); //查找目录
}
} catch (Exception e) {
e.printStackTrace();
}
}
3、查找目录/文件 、排序并显示
//搜索数据方法 传入目录 和 是否返回标识
private void findData(String sDcardDir, boolean isReturn) {
if (new File(sDcardDir).exists()) {//文件存在
Log.e("TAG", "222 path=" + sDcardDir);
File[] files = new File(sDcardDir).listFiles();
SearchFile(files);
Log.e("TAG", "last_mPos=" + last_mPos);//上一个目录的索引
if (isReturn){
mUnitAdapter.mPosSomeTime = last_mPos;
if(title.getText().toString().equals(root_name)){
mUnitAdapter.mPosSomeTime = first_mPos;
}
}else {
mUnitAdapter.mPosSomeTime = 0;
}
Log.e("TAG", "mUnitAdapter.mPosSomeTime=" + mUnitAdapter.mPosSomeTime);
if(unitList!=null && unitList.size()>0){
ListSort(unitList);//排序
mUnitAdapter.mCurPos = -1;
mUnitAdapter.updateData(unitList); //刷新列表
recyclerView.scrollToPosition(mUnitAdapter.mPosSomeTime);
}else {
isNoData = true;
}
} else {
isNoData = true;
toast("找不到相关文件");
}
//隐藏或显示 无数据view/列表
ll_no_data.setVisibility(isNoData?View.VISIBLE:View.GONE);
recyclerView.setVisibility(isNoData?View.GONE:View.VISIBLE);
}private void SearchFile(File[] files) { //搜索文件
unitList.clear(); //清空上次搜索的文件列表
for (File file : files) {
if (file.isDirectory()) {
if (file.getName().contains("XX") || file.getName().contains("语文")) {
//自定义拦截条件 不显示这个文件
continue;
}
HashMap<String, String> map = new HashMap();//创建文件对象
if (file.getName().equals("英语"))) { //自定义显示文件名称
map.put("item", "XXX");
} else {
if (file.getName().contains("_")) { //截取_
map.put("item", file.getName().substring(file.getName().indexOf("_") + 1));
} else {
map.put("item", file.getName());//文件名称
}
}
map.put("path_name", file.getPath());//文件路径
map.put("file_type", "file");//文件夹类型
unitList.add(map);//加入列表 } else if (file.isFile()) {
String path = file.getPath();
String data_type = "";
if (path.endsWith(".XXX")) {//查找指定扩展名的文件
data_type = "xxx";
} else if (path.endsWith(".AAA")) {
data_type = "aaa";
} else if (path.endsWith(".BBB")) {
data_type = "bbb";
} if (!TextUtils.isEmpty(data_type)) {
HashMap<String, String> map = new HashMap();
map.put("item", file.getName());
map.put("path_name", file.getPath());
map.put("data_type", data_type);
map.put("file_type", "book");//具体文件类型 比如书本
unitList.add(map);
}
}
}
if (unitList == null || unitList.size() == 0) {
toast("找不到相关文件");
mUnitAdapter.updateData(unitList);
isNoData = true;
}else {
isNoData = false;
}
}//按年级排序
private ArrayList<HashMap<String, String>> ListSort(ArrayList> list){
if(list.get(0).get("file_type").equals("file")){
for (int i = 0; i < list.size(); i++) {
String item=list.get(i).get("item");
if (TextUtils.isEmpty(item)){
break;
}
if(item.contains("一年级") || item.contains("1年级") || item.contains("人民教育")){
list.get(i).put("index", "1");
}else if(item.contains("二年级") || item.contains("2年级")){
list.get(i).put("index", "2");
}else if(item.contains("三年级") || item.contains("3年级")){
list.get(i).put("index", "3");
}else if(item.contains("四年级") || item.contains("4年级")){
list.get(i).put("index", "4");
}else if(item.contains("五年级") || item.contains("5年级")){
list.get(i).put("index", "5");
}else if(item.contains("六年级") || item.contains("6年级")){
list.get(i).put("index", "6");
}else if(item.contains("七年级") || item.contains("7年级")){
list.get(i).put("index", "7");
}else if(item.contains("八年级") || item.contains("8年级")){
list.get(i).put("index", "8");
}else if(item.contains("九年级") || item.contains("9年级")){
list.get(i).put("index", "9");
}else {
list.get(i).put("index", (i+10)+"");
}
} Comparator<HashMap<String, String>> comparator = (details1, details2) -> {
if (details1.get("index") != null && (Integer.parseInt(details1.get("index")) > Integer.parseInt(details2.get("index")))) {
return 1;
} else if (details1.get("index") != null && (Integer.parseInt(details1.get("index")) < Integer.parseInt(details2.get("index")))) {
return -1;
} else {
相关文章
-
甜瓜游乐场如何自制角色
05-30
-
DeepSeek-OCR-2 发布:支持多模态图文理解的二代 OCR 模型
05-30
-
中通快递单号怎么查询官网
05-30
-
燕云十六声爱的供养成就攻略-成就爱的供养如何完成
05-30
-
OpenAI与谷歌加码新加坡AI投资,争夺东南亚市场
05-30
-
墨境公测时间是什么时候
05-30