gpt4 book ai didi

android - 创建一个可扩展的 RecyclerView

转载 作者:IT老高 更新时间:2023-10-28 23:11:31 26 4
gpt4 key购买 nike

我正在尝试实现一个 recyclerview,其行为类似于我下面的草图:

enter image description here

这个想法是有一个父列表,当点击父列表中的列表项时,该列表项会显示一个包含它自己的数据的子列表。在子列表中点击列表项时,会反射(reflect)该子项的值并更新父列表项中父项的值。

在过去的 3 天里,我试图让它工作,但无济于事。我尝试使用 AdvancedReyclerview library但是对于像我这样的初学者来说,这是一堆没有意义的东西,尤其是在传递数据时。我复制并粘贴了获得最小工作版本所需的文件,但我不知道如何将我的数据传递到 recyclerview 以及如何使用新选择的值对其进行更新。

是否有可能做我想做的事情,或者我在这里超出了我的深度?

如果还是难以理解,我可以再解释一下。

编辑:有人建议我使用 ExpandableListView 而不是 RecyclerView。对此有什么想法吗?

最佳答案

1.ExpandableRecyclerAdapter.class

public abstract class ExpandableRecyclerAdapter<T extends ExpandableRecyclerAdapter.ListItem> extends RecyclerView.Adapter<ExpandableRecyclerAdapter.ViewHolder> {
protected Context mContext;
protected List<T> allItems = new ArrayList<>();
protected List<T> visibleItems = new ArrayList<>();
private List<Integer> indexList = new ArrayList<>();
private SparseIntArray expandMap = new SparseIntArray();
private int mode;

protected static final int TYPE_HEADER = 1000;

private static final int ARROW_ROTATION_DURATION = 150;

public static final int MODE_NORMAL = 0;
public static final int MODE_ACCORDION = 1;

public ExpandableRecyclerAdapter(Context context) {
mContext = context;
}

public static class ListItem {
public int ItemType;

public ListItem(int itemType) {
ItemType = itemType;
}
}

@Override
public long getItemId(int i) {
return i;
}

@Override
public int getItemCount() {
return visibleItems == null ? 0 : visibleItems.size();
}

protected View inflate(int resourceID, ViewGroup viewGroup) {
return LayoutInflater.from(mContext).inflate(resourceID, viewGroup, false);
}

public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View view) {
super(view);
}
}

public class HeaderViewHolder extends ViewHolder {
ImageView arrow;

public HeaderViewHolder(View view) {
super(view);

view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toggleExpandedItems(getLayoutPosition(),false);
/*if(isExpanded(getLayoutPosition())){
collapseItems(getLayoutPosition(),false);
}else {
expandItems(getLayoutPosition(),true);
}*/
}
});
}

public HeaderViewHolder(View view, final ImageView arrow) {
super(view);

this.arrow = arrow;

arrow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handleClick();
}
});
}

protected void handleClick() {
if (toggleExpandedItems(getLayoutPosition(), false)) {
openArrow(arrow);
} else {
closeArrow(arrow);
}
}

public void bind(int position) {
arrow.setRotation(isExpanded(position) ? 90 : 0);
}
}

public boolean toggleExpandedItems(int position, boolean notify) {
if (isExpanded(position)) {
collapseItems(position, notify);
return false;
} else {
expandItems(position, notify);

if (mode == MODE_ACCORDION) {
collapseAllExcept(position);
}

return true;
}
}

public void expandItems(int position, boolean notify) {
int count = 0;
int index = indexList.get(position);
int insert = position;

for (int i=index+1; i<allItems.size() && allItems.get(i).ItemType != TYPE_HEADER; i++) {
insert++;
count++;
visibleItems.add(insert, allItems.get(i));
indexList.add(insert, i);
}

notifyItemRangeInserted(position + 1, count);

int allItemsPosition = indexList.get(position);
expandMap.put(allItemsPosition, 1);

if (notify) {
notifyItemChanged(position);
}
}

public void collapseItems(int position, boolean notify) {
int count = 0;
int index = indexList.get(position);

for (int i=index+1; i<allItems.size() && allItems.get(i).ItemType != TYPE_HEADER; i++) {
count++;
visibleItems.remove(position + 1);
indexList.remove(position + 1);
}

notifyItemRangeRemoved(position + 1, count);

int allItemsPosition = indexList.get(position);
expandMap.delete(allItemsPosition);

if (notify) {
notifyItemChanged(position);
}
}


protected boolean isExpanded(int position) {
int allItemsPosition = indexList.get(position);
return expandMap.get(allItemsPosition, -1) >= 0;
}

@Override
public int getItemViewType(int position) {
return visibleItems.get(position).ItemType;
}

public void setItems(List<T> items) {
allItems = items;
List<T> visibleItems = new ArrayList<>();
expandMap.clear();
indexList.clear();

for (int i=0; i<items.size(); i++) {
if (items.get(i).ItemType == TYPE_HEADER) {
indexList.add(i);
visibleItems.add(items.get(i));
}
}

this.visibleItems = visibleItems;
notifyDataSetChanged();
}



protected void removeItemAt(int visiblePosition) {
int allItemsPosition = indexList.get(visiblePosition);

allItems.remove(allItemsPosition);
visibleItems.remove(visiblePosition);

incrementIndexList(allItemsPosition, visiblePosition, -1);
incrementExpandMapAfter(allItemsPosition, -1);

notifyItemRemoved(visiblePosition);
}

private void incrementExpandMapAfter(int position, int direction) {
SparseIntArray newExpandMap = new SparseIntArray();

for (int i=0; i<expandMap.size(); i++) {
int index = expandMap.keyAt(i);
newExpandMap.put(index < position ? index : index + direction, 1);
}

expandMap = newExpandMap;
}

private void incrementIndexList(int allItemsPosition, int visiblePosition, int direction) {
List<Integer> newIndexList = new ArrayList<>();

for (int i=0; i<indexList.size(); i++) {
if (i == visiblePosition) {
if (direction > 0) {
newIndexList.add(allItemsPosition);
}
}

int val = indexList.get(i);
newIndexList.add(val < allItemsPosition ? val : val + direction);
}

indexList = newIndexList;
}

public void collapseAll() {
collapseAllExcept(-1);
}

public void collapseAllExcept(int position) {
for (int i=visibleItems.size()-1; i>=0; i--) {
if (i != position && getItemViewType(i) == TYPE_HEADER) {
if (isExpanded(i)) {
collapseItems(i, true);
}
}
}
}

public void expandAll() {
for (int i=visibleItems.size()-1; i>=0; i--) {
if (getItemViewType(i) == TYPE_HEADER) {
if (!isExpanded(i)) {
expandItems(i, true);
}
}
}
}

public static void openArrow(View view) {
view.animate().setDuration(ARROW_ROTATION_DURATION).rotation(180);

}

public static void closeArrow(View view) {
view.animate().setDuration(ARROW_ROTATION_DURATION).rotation(0);
}

public int getMode() {
return mode;
}

public void setMode(int mode) {
this.mode = mode;
}
}

2.activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView android:id="@+id/main_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />

3.item_header

<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
android:orientation="horizontal"
android:padding="@dimen/standard_padding">

<LinearLayout
android:id="@+id/lnr_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true">

<TextView
android:id="@+id/txt_header_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@mipmap/ic_usa"
android:gravity="center"
android:text="Beverly Hills"
android:textStyle="bold" />

</LinearLayout>

<ImageView
android:id="@+id/img_arrow"
android:layout_width="@dimen/arrow_size"
android:layout_height="@dimen/arrow_size"
android:layout_alignParentRight="true"
android:src="@mipmap/arrow" />

<TextView
android:id="@+id/txt_header_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:text="Home"
android:textStyle="bold" />

4.item_content.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<RelativeLayout
android:id="@+id/rcl_header_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">

<Button
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn_cancle" />

<Button
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="@string/btn_save" />

</RelativeLayout>

<LinearLayout
android:id="@+id/lnr_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/rcl_header_btn"
android:gravity="center_vertical"
android:orientation="vertical">

<EditText
android:id="@+id/edt_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="DESCRIPTION" />

<EditText
android:id="@+id/edt_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Address" />

<LinearLayout
android:id="@+id/lnr_child_1"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<EditText
android:id="@+id/edt_city"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="City" />

<EditText
android:id="@+id/edt_state"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="State" />

</LinearLayout>

<LinearLayout
android:id="@+id/lnr_child_2"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<EditText
android:id="@+id/edt_zipcode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Zip Code" />

<EditText
android:id="@+id/edt_country"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Country" />

</LinearLayout>
</LinearLayout>

<RelativeLayout
android:id="@+id/rcl_bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/lnr_parent">

<CheckBox
android:id="@+id/chk_marked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/txt_type" />

<TextView
android:id="@+id/txt_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/btn_delete"
android:layout_toRightOf="@+id/chk_marked"
android:gravity="center"
android:text="SET AS DEFAULT" />

<Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="DELETE" />

</RelativeLayout>

5.Adapter

public class PeopleAdapter extends ExpandableRecyclerAdapter<PeopleAdapter.PeopleListItem> {
public static final int TYPE_PERSON = 1001;

public PeopleAdapter(Context context) {
super(context);

setItems(getSampleItems());
}

public static class PeopleListItem extends ExpandableRecyclerAdapter.ListItem {
public String Text;

public PeopleListItem(String group) {
super(TYPE_HEADER);

Text = group;
}

public PeopleListItem(String first, String last) {
super(TYPE_PERSON);

Text = first + " " + last;
}
}

public class HeaderViewHolder extends ExpandableRecyclerAdapter.HeaderViewHolder {
TextView name;

public HeaderViewHolder(View view) {
super(view, (ImageView) view.findViewById(R.id.img_arrow));

name = (TextView) view.findViewById(R.id.txt_header_name);
}

public void bind(int position) {
super.bind(position);

name.setText(visibleItems.get(position).Text);
}
}

public class PersonViewHolder extends ExpandableRecyclerAdapter.ViewHolder {
EditText name;

public PersonViewHolder(View view) {
super(view);

name = (EditText) view.findViewById(R.id.edt_description);
}

public void bind(int position) {
name.setText(name.getText());
}

}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_HEADER:
return new HeaderViewHolder(inflate(R.layout.item_header, parent));
case TYPE_PERSON:
default:
return new PersonViewHolder(inflate(R.layout.item_content, parent));
}
}

@Override
public void onBindViewHolder(ExpandableRecyclerAdapter.ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case TYPE_HEADER:
((HeaderViewHolder) holder).bind(position);
break;
case TYPE_PERSON:
default:
((PersonViewHolder) holder).bind(position);
break;
}
}

private List<PeopleListItem> getSampleItems() {
List<PeopleListItem> items = new ArrayList<>();
items.add(new PeopleListItem("Friends"));
items.add(new PeopleListItem("", ""));
items.add(new PeopleListItem("Friends"));
items.add(new PeopleListItem("", ""));
return items;
}

}

6.MainActivity.java

public class MainActivity extends AppCompatActivity {
RecyclerView recycler;
PeopleAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

recycler = (RecyclerView) findViewById(R.id.main_recycler);

adapter = new PeopleAdapter(this);
adapter.setMode(ExpandableRecyclerAdapter.MODE_ACCORDION);
recycler.setLayoutManager(new LinearLayoutManager(this));
recycler.setAdapter(adapter);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);

getMenuInflater().inflate(R.menu.menu_main, menu);

return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_expand_all:
adapter.expandAll();
return true;
case R.id.action_collapse_all:
adapter.collapseAll();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}

关于android - 创建一个可扩展的 RecyclerView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29887123/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com