為RecyclerView新增點選事件、長按事件
阿新 • • 發佈:2018-12-18
本篇展示手機內已安裝的軟體資訊,並新增事件,效果如下
一、準備工作
儲存App資訊的bean
public class AppInfo { public String name; // 應用名 public String packageName; // 應用包名 public Drawable icon; // 應用圖示 public boolean isRom; // 應用的安裝位置 public boolean isUser; // 系統還是使用者應用
獲取手機所有App的資訊
可以瞭解獲取系統資訊的相關APIpublic class AppInfoProvider { /** * 獲取已安裝應用 */ public static ArrayList<AppInfo> getIntalledApps(Context ctx) { PackageManager pm = ctx.getPackageManager(); List<PackageInfo> installedPackages = pm.getInstalledPackages(0
activity_main
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.RecyclerView android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
展示App資訊的條目佈局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="5dp"> <ImageView android:id="@+id/iv_icon" android:layout_width="45dp" android:layout_height="45dp" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:src="@mipmap/ic_launcher"/> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginLeft="20dp" android:layout_marginTop="2dp" android:layout_toRightOf="@+id/iv_icon" android:singleLine="true" android:text="名稱" android:textColor="#000" android:textSize="18sp"/> <TextView android:id="@+id/tv_location" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/iv_icon" android:layout_alignLeft="@+id/tv_name" android:layout_marginTop="3dp" android:text="手機記憶體" android:textColor="#000" android:textSize="16sp"/> </RelativeLayout>
頭佈局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/tv_head" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#9e9e9e" android:padding="5dp" android:text="使用者應用(0)" android:textColor="#fff" android:textSize="16sp"/> </LinearLayout>
二、介面卡(★)
事件的新增需要我們手動進行,分別新增點選和長按介面,介面中新增抽象方法,引數為當前佈局物件和點選的條目的位置,然後繫結到當前實現的
View.OnClickListener
介面的onClick()
方法中,具體過程請看本篇最後第四章
public class AppAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements View.OnClickListener, View.OnLongClickListener {
public static final int TYPE_HEAD = 0;
public static final int TYPE_APPS = 1;
// 這裡資料來源有兩個(系統應用列表和使用者應用列表)
private ArrayList<AppInfo> mUserList; // 所有已安裝使用者應用的集合
private ArrayList<AppInfo> mSystemList; // 所有已安裝系統應用的集合
public AppAdapter(ArrayList<AppInfo> userList, ArrayList<AppInfo> systemList) {
mUserList = userList;
mSystemList = systemList;
}
@Override public int getItemViewType(int position) {
if (position == 0 || position == mUserList.size() + 1) {
return TYPE_HEAD;
} else {
return TYPE_APPS;
}
}
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = null;
RecyclerView.ViewHolder holder = null;
switch (viewType) {
case TYPE_HEAD:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_header, null);
holder = new HeadHolder(view);
break;
case TYPE_APPS:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_appinfo, null);
/**
* 為展示應用資訊的佈局新增點選和長按事件監聽
*/
view.setOnClickListener(this);
view.setOnLongClickListener(this);
holder = new AppsHolder(view);
break;
}
return holder;
}
@Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case TYPE_HEAD:
if (0 == position) {
((HeadHolder) holder).tvHead.setText("使用者應用(" +mUserList.size() + ")");
} else {
((HeadHolder) holder).tvHead.setText("系統應用(" + mSystemList.size() + ")");
}
break;
case TYPE_APPS:
AppInfo info;
if (position < mUserList.size() + 1) {
info = mUserList.get(position - 1); // 從使用者應用列表中獲取應用資訊
} else {
info = mSystemList.get(position - mUserList.size() - 2); // 從系統應用列表中獲取應用資訊
}
// 設定控制元件內容
((AppsHolder) holder).tvName.setText(info.name);
((AppsHolder) holder).ivIcon.setImageDrawable(info.icon);
if (info.isRom) {
((AppsHolder) holder).tvLocation.setText("內建儲存卡");
} else {
((AppsHolder) holder).tvLocation.setText("外部儲存卡");
}
/**
* 將position儲存在itemView的Tag中以便點選時獲取
*/
holder.itemView.setTag(position);
break;
}
}
@Override public int getItemCount() {
return mUserList.size() + mSystemList.size() + 2; // 加上兩條頭佈局條目
}
/****************************************
* Holder
*/
class HeadHolder extends RecyclerView.ViewHolder {
@BindView(R.id.tv_head) TextView tvHead;
public HeadHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
class AppsHolder extends RecyclerView.ViewHolder {
@BindView(R.id.tv_name) TextView tvName;
@BindView(R.id.iv_icon) ImageView ivIcon;
@BindView(R.id.tv_location) TextView tvLocation;
public AppsHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
/****************************************
* Listener
*/
/**
* 手動新增點選事件
*/
interface OnClickListener {
void onClick(View view, int position);
}
private OnClickListener mOnClickListener = null;
public void setOnClickListener(OnClickListener listener) {
mOnClickListener = listener;
}
@Override public void onClick(View view) {
if (null != mOnClickListener) {
mOnClickListener.onClick(view, (int) view.getTag());
}
}
/**
* 手動新增長按事件
*/
interface OnLongClickListener {
void onLongClick(View view, int position);
}
private OnLongClickListener mOnLongClickListener = null;
public void setOnLongClickListener(OnLongClickListener listener) {
mOnLongClickListener = listener;
}
@Override public boolean onLongClick(View view) {
if (null != mOnLongClickListener) {
mOnLongClickListener.onLongClick(view, (int) view.getTag());
}
// 消耗事件,否則長按邏輯執行完成後還會進入點選事件的邏輯處理
return true;
}
}
三、Activity中使用
重點看
setAdapter
之後的點選和長按事件的具體處理邏輯即可
public class AppsActivity extends AppCompatActivity {
@BindView(R.id.rv) RecyclerView rv;
private AppAdapter mAdapter;
private LinearLayoutManager mLayoutManager;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_apps);
ButterKnife.bind(this);
initData(); // 初始化資料
rv.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
rv.setLayoutManager(mLayoutManager);
rv.setItemAnimator(new DefaultItemAnimator());
mAdapter = new AppAdapter(mUserList, mSystemList);
rv.setAdapter(mAdapter);
/**
* 點選和長按事件的具體處理
*/
mAdapter.setOnClickListener(new AppAdapter.OnClickListener() {
@Override public void onClick(View view, int position) {
if (position < mUserList.size() + 1) {
Toast.makeText(AppsActivity.this, mUserList.get(position - 1).name, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(AppsActivity.this, mSystemList.get(position - mUserList.size() - 2).name, Toast.LENGTH_SHORT).show();
}
}
});
mAdapter.setOnLongClickListener(new AppAdapter.OnLongClickListener() {
@Override public void onLongClick(View view, int position) {
if (position < mUserList.size() + 1) {
Toast.makeText(AppsActivity.this, "長按" + mUserList.get(position - 1).name, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(AppsActivity.this, "長按" + mSystemList.get(position - mUserList.size() - 2).name, Toast.LENGTH_SHORT).show();
}
}
});
}
private ArrayList<AppInfo> mList; // 所有已安裝應用的集合
private ArrayList<AppInfo> mUserList; // 所有已安裝使用者應用的集合
private ArrayList<AppInfo> mSystemList; // 所有已安裝系統應用的集合
private void initData() {
mList = AppInfoProvider.getIntalledApps(getApplicationContext());
// 區分使用者和系統應用,分別放在兩個集合中
mUserList = new ArrayList<AppInfo>();
mSystemList = new ArrayList<AppInfo>();
for (AppInfo info : mList) {
if (info.isUser) {
mUserList.add(info);
} else {
mSystemList.add(info);
}
}
}
}
四、點選事件實現過程
定義點選事件介面
在
onCreateViewHolder()
中為每個條目新增點選事件在
onBindViewHolder()
中設定被點選條目的position在
View.OnClickListener
的onClick()
方法中將事件傳遞給外面的呼叫者