RecyclerView - 拖放 - 将项目移动到另一个项目上。 (占位符)
RecyclerView - Drag and Drop - move item over another item. (placeholder)
我有一个适配器、Recyclerview 和 ItemTouchHelper。
我想制作占位符,由于移动,可以在其上放置物品。
占位符现在被制作成空元素。但是我不知道怎么把元素直接放在这个上面
我的适配器:
public class DateTimeAdapter extends RecyclerView.Adapter<MainHolder> implements ItemTouchHelperAdapter {
private List<MainItem> values;
private RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
private Activity context;
private final OnStartDragListener mDragStartListener;
private boolean initEmpty = false;
public DateTimeAdapter(Activity context, List<MainItem> values, OnStartDragListener dragListener) {
this.values = values;
this.context = context;
mDragStartListener = dragListener;
}
@NonNull
@Override
public MainHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
switch (viewType){
case (Constants.ITEM_HEADER_TEXT_VIEWTYPE):
view = LayoutInflater.from(context).inflate(R.layout.list_group_item, parent, false);
return new HeaderHolder(view);
case (Constants.ITEM_EVENT_TEXT_VIEWTYPE):
view = LayoutInflater.from(context).inflate(R.layout.item_wo_items, parent, false);
return new ItemHolder(view);
case (Constants.ITEM_PLACEHOLDER_VIEWTYPE):
view = LayoutInflater.from(context).inflate(R.layout.item_placeholder, parent, false);
return new PlaceHolder(view);
default: throw new IllegalArgumentException();
}
}
@Override
public void onBindViewHolder(@NonNull final MainHolder holder, int position) {
holder.setData(values.get(position));
if (holder.getItemViewType() == Constants.ITEM_PLACEHOLDER_VIEWTYPE){
}
}
@Override
public int getItemCount() {
return values.size();
}
@Override
public int getItemViewType(int position) {
return values.get(position).getViewType();
}
protected LocalTime getStartTimebyHeader(int position){
ListIterator<MainItem> listIterator = values.listIterator(position);
while (listIterator.hasPrevious()){
MainItem t = listIterator.previous();
if (t.getHeaderItem() != null){
DateTimeFormatter parse = new DateTimeFormatterBuilder().appendPattern("HH:mm").toFormatter();
LocalTime localTime = LocalTime.parse(t.getHeaderItem().getHeaderText(), parse);
return localTime;
}
}
return null;
}
protected LocalTime getEndTimebyHeader(int position){
ListIterator<MainItem> listIterator = values.listIterator(position);
while (listIterator.hasNext()){
MainItem t = listIterator.next();
if (t.getHeaderItem() != null){
DateTimeFormatter parse = new DateTimeFormatterBuilder().appendPattern("HH:mm").toFormatter();
LocalTime localTime = LocalTime.parse(t.getHeaderItem().getHeaderText(), parse);
return localTime;
}
}
return null;
}
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(values, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(values, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
return true;
}
@Override
public void onItemDismiss(int position) {
values.remove(position);
notifyItemRemoved(position);
}
}
我的 ItemTouchHelper
ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0, 0) {
@Override
public boolean canDropOver(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder current, @NonNull RecyclerView.ViewHolder target) {
if (target.getAdapterPosition() != 0 && target.getAdapterPosition() != dta.getItemCount()-1)
return true;
return false;
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
Log.d("onMove", Integer.toString(viewHolder.getAdapterPosition()) + " - " + Integer.toString(target.getAdapterPosition()));
dta.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
}
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
int dragFlags = viewHolder.getItemViewType() == Constants.ITEM_EVENT_TEXT_VIEWTYPE ? ItemTouchHelper.UP | ItemTouchHelper.DOWN : 0;
int swipeFlags = viewHolder.getItemViewType() == Constants.ITEM_EVENT_TEXT_VIEWTYPE ? ItemTouchHelper.START | ItemTouchHelper.END : 0;
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
showingDatas.get(viewHolder.getAdapterPosition()).getEventItem().setTimeS(dta.getStartTimebyHeader(viewHolder.getAdapterPosition()));
showingDatas.get(viewHolder.getAdapterPosition()).getEventItem().setTimeE(dta.getEndTimebyHeader(viewHolder.getAdapterPosition()));
dta.notifyItemChanged(viewHolder.getAdapterPosition());
super.clearView(recyclerView, viewHolder);
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleCallback);
itemTouchHelper.attachToRecyclerView(rvPlan);
我应该怎么做?
问题已解决:数据class用于区分普通视图和占位符视图。在适配器中使用以下列表:
data class MyData(var type:Int, var name: String)
val list = mutableListOf(MyData(0,"PlaceHolder"),MyData(1,"Normal"),MyData(1,"Noraml"),MyData(0,"Place Holder"),MyData(1,"Normal"),MyData(1,"Normal"))
自定义项目触摸监听器class:
ItemTouchHelper(object : RecyclerViewDragDetector() {
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
if (adapter.getItemViewType(viewHolder.adapterPosition) == 1){
if (adapter.getItemViewType(target.adapterPosition)!= 1){
list[target.adapterPosition].type = 1
list[target.adapterPosition].name = "Normal"
adapter.notifyItemChanged(target.adapterPosition)
list.removeAt(viewHolder.adapterPosition)
adapter.notifyDataSetChanged()
}
}
return true
}
override fun isLongPressDragEnabled(): Boolean {
return true
}
}).attachToRecyclerView(recyclerView)
根据需要更换适配器。我的示例适配器如下所示:
inner class MyAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>(){
private val viewTypeHeader = 0
private val viewTypeNormal = 1
inner class MyHolder(view: View): RecyclerView.ViewHolder(view){
val textView: TextView = view.findViewById(R.id.normal_tv)
fun bind(myData: MyData){
textView.text = myData.name
}
}
inner class MyHeaderHolder(view:View): RecyclerView.ViewHolder(view){
val textView: TextView = view.findViewById(R.id.header_tv)
fun bind(myData: MyData){
textView.text = myData.name
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return if (viewType == viewTypeHeader){
val view = LayoutInflater.from(parent.context).inflate(R.layout.header, parent, false)
MyHeaderHolder(view)
}else {
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
MyHolder(view)
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (getItemViewType(position) == viewTypeHeader){
(holder as MyHeaderHolder).bind(list[position])
}else{
(holder as MyHolder).bind(list[position])
}
}
override fun getItemViewType(position: Int): Int {
return if (list[position].type == viewTypeHeader)
return viewTypeHeader
else
viewTypeNormal
}
override fun getItemCount(): Int {
return list.size
}
}
我有一个适配器、Recyclerview 和 ItemTouchHelper。 我想制作占位符,由于移动,可以在其上放置物品。 占位符现在被制作成空元素。但是我不知道怎么把元素直接放在这个上面
我的适配器:
public class DateTimeAdapter extends RecyclerView.Adapter<MainHolder> implements ItemTouchHelperAdapter {
private List<MainItem> values;
private RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
private Activity context;
private final OnStartDragListener mDragStartListener;
private boolean initEmpty = false;
public DateTimeAdapter(Activity context, List<MainItem> values, OnStartDragListener dragListener) {
this.values = values;
this.context = context;
mDragStartListener = dragListener;
}
@NonNull
@Override
public MainHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
switch (viewType){
case (Constants.ITEM_HEADER_TEXT_VIEWTYPE):
view = LayoutInflater.from(context).inflate(R.layout.list_group_item, parent, false);
return new HeaderHolder(view);
case (Constants.ITEM_EVENT_TEXT_VIEWTYPE):
view = LayoutInflater.from(context).inflate(R.layout.item_wo_items, parent, false);
return new ItemHolder(view);
case (Constants.ITEM_PLACEHOLDER_VIEWTYPE):
view = LayoutInflater.from(context).inflate(R.layout.item_placeholder, parent, false);
return new PlaceHolder(view);
default: throw new IllegalArgumentException();
}
}
@Override
public void onBindViewHolder(@NonNull final MainHolder holder, int position) {
holder.setData(values.get(position));
if (holder.getItemViewType() == Constants.ITEM_PLACEHOLDER_VIEWTYPE){
}
}
@Override
public int getItemCount() {
return values.size();
}
@Override
public int getItemViewType(int position) {
return values.get(position).getViewType();
}
protected LocalTime getStartTimebyHeader(int position){
ListIterator<MainItem> listIterator = values.listIterator(position);
while (listIterator.hasPrevious()){
MainItem t = listIterator.previous();
if (t.getHeaderItem() != null){
DateTimeFormatter parse = new DateTimeFormatterBuilder().appendPattern("HH:mm").toFormatter();
LocalTime localTime = LocalTime.parse(t.getHeaderItem().getHeaderText(), parse);
return localTime;
}
}
return null;
}
protected LocalTime getEndTimebyHeader(int position){
ListIterator<MainItem> listIterator = values.listIterator(position);
while (listIterator.hasNext()){
MainItem t = listIterator.next();
if (t.getHeaderItem() != null){
DateTimeFormatter parse = new DateTimeFormatterBuilder().appendPattern("HH:mm").toFormatter();
LocalTime localTime = LocalTime.parse(t.getHeaderItem().getHeaderText(), parse);
return localTime;
}
}
return null;
}
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(values, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(values, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
return true;
}
@Override
public void onItemDismiss(int position) {
values.remove(position);
notifyItemRemoved(position);
}
}
我的 ItemTouchHelper
ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0, 0) {
@Override
public boolean canDropOver(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder current, @NonNull RecyclerView.ViewHolder target) {
if (target.getAdapterPosition() != 0 && target.getAdapterPosition() != dta.getItemCount()-1)
return true;
return false;
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
Log.d("onMove", Integer.toString(viewHolder.getAdapterPosition()) + " - " + Integer.toString(target.getAdapterPosition()));
dta.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
}
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
int dragFlags = viewHolder.getItemViewType() == Constants.ITEM_EVENT_TEXT_VIEWTYPE ? ItemTouchHelper.UP | ItemTouchHelper.DOWN : 0;
int swipeFlags = viewHolder.getItemViewType() == Constants.ITEM_EVENT_TEXT_VIEWTYPE ? ItemTouchHelper.START | ItemTouchHelper.END : 0;
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
showingDatas.get(viewHolder.getAdapterPosition()).getEventItem().setTimeS(dta.getStartTimebyHeader(viewHolder.getAdapterPosition()));
showingDatas.get(viewHolder.getAdapterPosition()).getEventItem().setTimeE(dta.getEndTimebyHeader(viewHolder.getAdapterPosition()));
dta.notifyItemChanged(viewHolder.getAdapterPosition());
super.clearView(recyclerView, viewHolder);
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleCallback);
itemTouchHelper.attachToRecyclerView(rvPlan);
我应该怎么做?
问题已解决:数据class用于区分普通视图和占位符视图。在适配器中使用以下列表:
data class MyData(var type:Int, var name: String)
val list = mutableListOf(MyData(0,"PlaceHolder"),MyData(1,"Normal"),MyData(1,"Noraml"),MyData(0,"Place Holder"),MyData(1,"Normal"),MyData(1,"Normal"))
自定义项目触摸监听器class:
ItemTouchHelper(object : RecyclerViewDragDetector() {
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
if (adapter.getItemViewType(viewHolder.adapterPosition) == 1){
if (adapter.getItemViewType(target.adapterPosition)!= 1){
list[target.adapterPosition].type = 1
list[target.adapterPosition].name = "Normal"
adapter.notifyItemChanged(target.adapterPosition)
list.removeAt(viewHolder.adapterPosition)
adapter.notifyDataSetChanged()
}
}
return true
}
override fun isLongPressDragEnabled(): Boolean {
return true
}
}).attachToRecyclerView(recyclerView)
根据需要更换适配器。我的示例适配器如下所示:
inner class MyAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>(){
private val viewTypeHeader = 0
private val viewTypeNormal = 1
inner class MyHolder(view: View): RecyclerView.ViewHolder(view){
val textView: TextView = view.findViewById(R.id.normal_tv)
fun bind(myData: MyData){
textView.text = myData.name
}
}
inner class MyHeaderHolder(view:View): RecyclerView.ViewHolder(view){
val textView: TextView = view.findViewById(R.id.header_tv)
fun bind(myData: MyData){
textView.text = myData.name
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return if (viewType == viewTypeHeader){
val view = LayoutInflater.from(parent.context).inflate(R.layout.header, parent, false)
MyHeaderHolder(view)
}else {
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
MyHolder(view)
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (getItemViewType(position) == viewTypeHeader){
(holder as MyHeaderHolder).bind(list[position])
}else{
(holder as MyHolder).bind(list[position])
}
}
override fun getItemViewType(position: Int): Int {
return if (list[position].type == viewTypeHeader)
return viewTypeHeader
else
viewTypeNormal
}
override fun getItemCount(): Int {
return list.size
}
}