多级列表是ui入门,没什么特别需要注意的难点,直接上代码:
第一级列表窗口
/**
* 第一级列表
* 1.编辑状态下选中一个条目,会弹出底部操作栏
* 2.非编辑状态下选中条目会跳转到下一级
* 3.复选框使用ImageView而不是CheckBox
* 4.编辑状态下,按返回键回到非编辑状态
*/
public class SectionListActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "SectionListActivity";
@BindView(R.id.tv_title_middle)
TextView title;
@BindView(R.id.title_left)
ImageView back;
@BindView(R.id.discuss_list_view)
ListView mListView;
@BindView(R.id.edit_tv)
TextView edit;
@BindView(R.id.filter_tv)
TextView filter;
@BindView(R.id.discuss_toolbar)
LinearLayout mToolbar;
@BindView(R.id.discuss_close)
TextView btnClose;
@BindView(R.id.discuss_open)
TextView btnOpen;
@BindView(R.id.discuss_delete)
TextView btnDelete;
private Context mContext;
private boolean isEditable;
private List mClsSectionList;
private SectionListAdapter mAdapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_section_list);
//使用ButterKnife绑定控件
ButterKnife.bind(this);
initView();
initData();
initListener();
}
private void initData() {
mContext = this;
//初始状态为非编辑
setIsEditable(false);
//初始化数据源
mClsSectionList = new ArrayList<>();
mAdapter = new SectionListAdapter(mClsSectionList, mContext);
mListView.setAdapter(mAdapter);
initOfflineData(10);
}
//生成模拟数据
private void initOfflineData(int num) {
List clsSectionList = new ArrayList<>();
for (int i = 0; i < num; i++) {
ClsSection clsSection = new ClsSection();
clsSection.setIsClosed("isClosed" + i);
clsSection.setCloseDate("closeDate" + i);
clsSection.setSectionID("sectionID" + i);
clsSection.setSectionName("sectionName" + i);
clsSection.setSectionType("sectionType" + i);
clsSection.setSectionDesc("sectionDesc" + i);
clsSection.setSectionLogo("sectionLogo" + i);
clsSection.setSectionManagerID("sectionManagerID" + i);
clsSection.setSectionManager("sectionManager" + i);
clsSectionList.add(clsSection);
}
mClsSectionList.addAll(clsSectionList);
mAdapter.notifyDataSetChanged();
}
private void initView() {
title.setText("一级列表");
mToolbar.setVisibility(View.GONE);
filter.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_add_black_24dp, 0, 0, 0);
edit.setVisibility(View.VISIBLE);
filter.setVisibility(View.VISIBLE);
}
private void initListener() {
back.setOnClickListener(this);
edit.setOnClickListener(this);
btnClose.setOnClickListener(this);
btnDelete.setOnClickListener(this);
btnOpen.setOnClickListener(this);
filter.setOnClickListener(this);
mListView.setOnItemClickListener((parent, view, position, id) -> {
ClsSection clsSection = mClsSectionList.get(position);
if (getIsEditable()) {
//编辑状态下,点击条目checkbox为显示选中
if (clsSection.getIsCheckBoxVisible()) {
clsSection.setIsChecked(!clsSection.getIsChecked());
mAdapter.notifyDataSetChanged();
}
//有一个条目被选中就弹出工具条
for (int i = 0; i < mClsSectionList.size(); i++) {
ClsSection section = mClsSectionList.get(i);
if (section.getIsChecked()) {
mToolbar.setVisibility(View.VISIBLE);
break;
}
//否则隐藏工具条
if (i == mClsSectionList.size() - 1) {
mToolbar.setVisibility(View.GONE);
}
}
} else {
//非编辑状态下,点击条目直接跳转
String sectionID = clsSection.getSectionID();
Intent intent = new Intent(mContext, TopicListActivity.class);
intent.putExtra("sectionID", sectionID);
startActivity(intent);
}
});
}
@Override
public void onClick(View v) {
//编辑状态下点击返回回到非编辑状态
//非编辑状态下直接退出
if (v.getId() == R.id.title_left) {
if (getIsEditable()) {
switchEditable();
} else {
finish();
}
}
//点击编辑按钮切换编辑状态
if (v.getId() == R.id.edit_tv) {
switchEditable();
}
//新建页面
if (v.getId() == R.id.filter_tv) {
Intent intent = new Intent(mContext, SectionNewActivity.class);
startActivityForResult(intent, 15874);
}
//点击工具条不同按钮调用不同接口
switch (v.getId()) {
case R.id.discuss_delete:
case R.id.discuss_close:
case R.id.discuss_open:
Toast.makeText(mContext, "在此处调用接口!", Toast.LENGTH_SHORT).show();
}
}
@Override
//编辑状态下点击返回回到非编辑状态
//非编辑状态下直接退出
public void onBackPressed() {
if (getIsEditable()) {
switchEditable();
} else {
finish();
}
}
public boolean getIsEditable() {
return isEditable;
}
public void setIsEditable(boolean editable) {
isEditable = editable;
}
private void switchEditable() {
//将属性取反
setIsEditable(!getIsEditable());
//遍历并修改数据源
for (ClsSection clsSection : mClsSectionList) {
clsSection.setIsCheckBoxVisible(getIsEditable());
clsSection.setIsChecked(false);
}
//通知适配器刷新
mAdapter.notifyDataSetChanged();
//隐藏工具条
mToolbar.setVisibility(View.GONE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == 15874 && resultCode == RESULT_OK) {
refreshData();
}
super.onActivityResult(requestCode, resultCode, data);
}
private void refreshData() {
Toast.makeText(mContext, "在此处调用接口!", Toast.LENGTH_SHORT).show();
}
}
第二级列表窗口
/**
* 第二级列表,接收第一级列表的传过来的sectionID
*/
public class TopicListActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "TopicListActivity";
@BindView(R.id.section_list_view)
ListView mListView;
@BindView(R.id.tv_title_middle)
TextView title;
@BindView(R.id.title_left)
ImageView back;
@BindView(R.id.edit_tv)
TextView edit;
@BindView(R.id.filter_tv)
TextView filter;
@BindView(R.id.btn_delete_topic)
LinearLayout btnDelete;
private Context mContext;
private boolean isEditable;
private List mClsTopicList;
private TopicListAdapter mAdapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_topic_list);
ButterKnife.bind(this);
initView();
initData();
initListener();
}
private void initData() {
mContext = this;
setIsEditable(false);
String sectionID = getIntent().getStringExtra("sectionID");
requestData(sectionID);
mClsTopicList = new ArrayList<>();
mAdapter = new TopicListAdapter(mClsTopicList, mContext);
mListView.setAdapter(mAdapter);
initOfflineData(20);
}
private void requestData(String sectionID) {
Toast.makeText(mContext, "在此处调用接口", Toast.LENGTH_SHORT).show();
}
private void initOfflineData(int sum) {
List clsTopicList = new ArrayList<>();
for (int i = 0; i < sum; i++) {
ClsTopic clsTopic = new ClsTopic();
clsTopic.setRowNum(" rowNum" + i);
clsTopic.setSectionID(" sectionID" + i);
clsTopic.setSectionName(" sectionName" + i);
clsTopic.setSectionManager(" sectionManager" + i);
clsTopic.setTopicID(" topicID" + i);
clsTopic.setTitle(" title" + i);
clsTopic.setTopicDesc(" topicDesc" + i);
clsTopic.setCreateDate(" createDate" + i);
clsTopicList.add(clsTopic);
}
mClsTopicList.addAll(clsTopicList);
mAdapter.notifyDataSetChanged();
}
private void initView() {
title.setText("二级列表");
filter.setVisibility(View.GONE);
btnDelete.setVisibility(View.GONE);
edit.setVisibility(View.VISIBLE);
}
private void initListener() {
btnDelete.setOnClickListener(this);
edit.setOnClickListener(this);
back.setOnClickListener(this);
mListView.setOnItemClickListener((parent, view, position, id) -> {
ClsTopic clsTopic = mClsTopicList.get(position);
if (getIsEditable()) {
if (clsTopic.getIsCheckBoxVisible()) {
clsTopic.setIsChecked(!clsTopic.getIsChecked());
mAdapter.notifyDataSetChanged();
}
for (int i = 0; i < mClsTopicList.size(); i++) {
ClsTopic topic = mClsTopicList.get(i);
if (topic.getIsChecked()) {
btnDelete.setVisibility(View.VISIBLE);
break;
}
if (i == mClsTopicList.size() - 1) {
btnDelete.setVisibility(View.GONE);
}
}
} else {
String topicID = clsTopic.getTopicID();
Intent intent = new Intent(mContext, ReplyListActivity.class);
intent.putExtra("topicID", topicID);
startActivity(intent);
}
});
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.title_left) {
if (getIsEditable()) {
switchEditable();
} else {
finish();
}
}
if (v.getId() == R.id.edit_tv) {
switchEditable();
}
if (v.getId() == R.id.btn_delete_topic) {
Toast.makeText(mContext, "在此处调用接口", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onBackPressed() {
if (getIsEditable()) {
switchEditable();
} else {
finish();
}
}
private void switchEditable() {
setIsEditable(!getIsEditable());
for (ClsTopic clsTopic : mClsTopicList) {
clsTopic.setIsCheckBoxVisible(getIsEditable());
clsTopic.setIsChecked(false);
}
mAdapter.notifyDataSetChanged();
btnDelete.setVisibility(View.GONE);
}
public boolean getIsEditable() {
return isEditable;
}
public void setIsEditable(boolean editable) {
isEditable = editable;
}
}
第三级列表窗口
/**
* 第三级列表,接收第二级列表的传过来的topicID
*/
public class ReplyListActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "ReplyListActivity";
@BindView(R.id.reply_list_view)
ListView mListView;
@BindView(R.id.tv_title_middle)
TextView title;
@BindView(R.id.title_left)
ImageView back;
@BindView(R.id.edit_tv)
TextView edit;
@BindView(R.id.filter_tv)
TextView filter;
@BindView(R.id.btn_delete_reply)
LinearLayout btnDelete;
private Context mContext;
private List mClsReplyList;
private ReplyListAdapter mAdapter;
private boolean isEditable;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reply_list);
ButterKnife.bind(this);
initView();
initData();
initListener();
}
private void initData() {
mContext = this;
setIsEditable(false);
String topicID = getIntent().getStringExtra("topicID");
requestData(topicID);
mClsReplyList = new ArrayList<>();
mAdapter = new ReplyListAdapter(mClsReplyList, mContext);
mListView.setAdapter(mAdapter);
getOfflineData(20);
}
private void requestData(String topicID) {
Toast.makeText(mContext, "在此处调用接口!", Toast.LENGTH_SHORT).show();
}
private void getOfflineData(int num) {
List clsReplyLists = new ArrayList<>();
for (int i = 0; i < num; i++) {
ClsReply clsReply = new ClsReply();
clsReply.setRowNum("rowNum" + i);
clsReply.setTopicID("topicID" + i);
clsReply.setReplyID("replyID" + i);
clsReply.setReplyContent("replyContent" + i);
clsReply.setReplyTime("replyTime" + i);
clsReply.setReplyBoutiqueNum("replyBoutiqueNum" + i);
clsReply.setReplyTopicNum("replyTopicNum" + i);
clsReply.setReplyManID("replyManID" + i);
clsReply.setReplyManName("replyManName" + i);
clsReplyLists.add(clsReply);
}
mClsReplyList.addAll(clsReplyLists);
mAdapter.notifyDataSetChanged();
}
private void initView() {
title.setText("三级列表");
filter.setVisibility(View.GONE);
btnDelete.setVisibility(View.GONE);
edit.setVisibility(View.VISIBLE);
}
private void initListener() {
back.setOnClickListener(this);
edit.setOnClickListener(this);
btnDelete.setOnClickListener(this);
mListView.setOnItemClickListener((parent, view, position, id) -> {
ClsReply clsReply = mClsReplyList.get(position);
if (getIsEditable()) {
if (clsReply.getIsCheckBoxVisible()) {
clsReply.setIsChecked(!clsReply.getIsChecked());
mAdapter.notifyDataSetChanged();
}
for (int i = 0; i < mClsReplyList.size(); i++) {
ClsReply reply = mClsReplyList.get(i);
if (reply.getIsChecked()) {
btnDelete.setVisibility(View.VISIBLE);
break;
}
if (i == mClsReplyList.size() - 1) {
btnDelete.setVisibility(View.GONE);
}
}
} else {
String topicID = clsReply.getTopicID();
Toast.makeText(mContext, topicID, Toast.LENGTH_LONG).show();
}
});
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.title_left) {
if (getIsEditable()) {
switchEditable();
} else {
finish();
}
}
if (v.getId() == R.id.edit_tv) {
switchEditable();
}
if (v.getId() == R.id.btn_delete_reply) {
Toast.makeText(mContext, "在此处调用接口", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onBackPressed() {
if (getIsEditable()) {
switchEditable();
} else {
finish();
}
}
private void switchEditable() {
setIsEditable(!getIsEditable());
for (ClsReply clsReply : mClsReplyList) {
clsReply.setIsCheckBoxVisible(getIsEditable());
clsReply.setIsChecked(false);
}
mAdapter.notifyDataSetChanged();
btnDelete.setVisibility(View.GONE);
}
public boolean getIsEditable() {
return isEditable;
}
public void setIsEditable(boolean editable) {
isEditable = editable;
}
三个列表的逻辑其实差不多,任何一个都可以作用通用的模板使用,至于什么时候请求数据,什么时候调用接口,什么时候刷新,都看具体的需求而定
运行效果: