这是一个文件浏览器的例子,点击文件夹就会进入到这里文件夹,点button就返回上一级目录,用到了RecyclerView。
布局比较简单,最上面是个textview显示当前路径,然后是个button返回上级目录,最后是一个recyclerview用来显示文件列表。
先贴一下布局,然后看怎么使用recyclerview实现。
mainactivity.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/back" />
<TextView
android:id="@+id/path"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/path" />
</android.support.constraint.ConstraintLayout>
item
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintStart_toEndOf="@+id/icon"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
1.自定义 RecyclerView.adapter和RecyclerView.ViewHolder
我们这里的list使用的是标准的类型(File,类似的还有String等),所以没有额外新建自己的类。
这里使用了自定义接口的方法来实现的item的点击事件。当然你也可以直接在onBindViewHolder方法中直接实现,类似listview中的geview。
package com.example.sdcardbrowser;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.File;
import java.util.List;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private Context context;
private List<File> list;
//自定义点击接口,可以在activity中使用。 你也可以直接在onBindViewHolder中写点击事件。
private MyViewHolder.OnItemClickListener mListener;
public MyAdapter(Context context, List<File> list) {
this.context = context;
this.list = list;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.item, null);
return new MyViewHolder(view,mListener);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int i) {
File file = list.get(i);
myViewHolder.txt_path.setText(file.getName());
if (file.isDirectory()) {
myViewHolder.icon.setImageResource(R.drawable.folder);
} else {
myViewHolder.icon.setImageResource(R.drawable.file);
}
}
public void setOnItemClickListener(MyViewHolder.OnItemClickListener listener){
mListener=listener;
}
@Override
public int getItemCount() {
return list.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView txt_path;
ImageView icon;
OnItemClickListener mListener;
public MyViewHolder(@NonNull View itemView,OnItemClickListener listener) {
super(itemView);
//定义了点击事件,然后在里面调用自己定义的接口(点击事件)
mListener=listener;
itemView.setOnClickListener(this);
txt_path=itemView.findViewById(R.id.name);
icon=itemView.findViewById(R.id.icon);
}
@Override
public void onClick(View view) {
mListener.onItemClick(view,getAdapterPosition());
}
public interface OnItemClickListener{
void onItemClick(View view,int position);
}
}
}
2.在activity中使用
package com.example.sdcardbrowser;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class MainActivity extends AppCompatActivity implements MyAdapter.MyViewHolder.OnItemClickListener, View.OnClickListener {
private RecyclerView recyclerView;
private TextView txt_path;
private Button btn_previous;
private File currentParent;
private File[] currentFiles;
private String[] permissions = new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
private MyAdapter myAdapter;
private List<File> myList=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//使用RecyclerView的基本步骤
recyclerView = findViewById(R.id.list);
//设置一个布局管理,你也可以设置横向滑动,还可以设置动画等
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
txt_path = findViewById(R.id.path);
btn_previous=findViewById(R.id.back);
btn_previous.setOnClickListener(this);
myAdapter=new MyAdapter(this,myList);
//设置我们自定义点击事件监听
myAdapter.setOnItemClickListener(this);
//给RecyclerView设置adapter
recyclerView.setAdapter(myAdapter);
requestPermissions(permissions, 1);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == 1) {
Log.d("a",""+grantResults[0]);
if (grantResults != null && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
File root = Environment.getExternalStorageDirectory();
if (root.exists()) {
currentParent = root;
currentFiles = root.listFiles();
Collections.addAll(myList,currentFiles);
myAdapter.notifyDataSetChanged();
txt_path.setText(currentParent.toString());
}
} else {
Toast.makeText(this, "no permission", Toast.LENGTH_SHORT).show();
}
}
}
//自定义item点击事件的实现
@Override
public void onItemClick(View view, int position) {
if(currentFiles[position].isFile()) return;
File[] tmp=currentFiles[position].listFiles();
if(tmp==null||tmp.length==0){
Toast.makeText(this,"no files",Toast.LENGTH_SHORT).show();
}else {
currentParent=currentFiles[position];
currentFiles=tmp;
myList.clear();
//数组与list的转换
Collections.addAll(myList,currentFiles);
myAdapter.notifyDataSetChanged();
txt_path.setText(currentParent.toString());
}
}
@Override
public void onClick(View view) {
if(!Environment.getExternalStorageDirectory().equals(currentParent)){
currentParent=currentParent.getParentFile();
currentFiles=currentParent.listFiles();
myList.clear();
Collections.addAll(myList,currentFiles);
myAdapter.notifyDataSetChanged();
}
}
}