我创建了一个带有“事件”列表的recyclerview。对于小于5个事件的事件列表,它可以正常工作。但是,一旦事件列表中的事件数量超过6个,最后一个事件在被点击后不会展开,而是消失。当事件列表中的事件超过6个时,关闭动画也停止工作。
应该的行为:
- 用户点击事件,视图展开到全屏状态 - 用户点击已展开的事件,视图回缩到原始大小 - 当另一个事件已经展开时,用户点击事件,展开的事件返回原始高度,并将点击的事件扩大到全屏状态
当前的行为:
- 用户点击事件,除了列表中的最后一项之外,所有视图都会正确展开 - 用户点击已展开的事件,视图会回缩但没有动画效果 - 当另一个事件已经展开时,用户点击事件,展开的事件回缩并且点击的事件正确扩大到全屏状态 - 用户点击列表中的最后一个事件,该事件会消失(可能已经缩小到小于0)
我知道这可能与recyclerview在屏幕上不可见时如何重用其视图的方式有关。为了解决此问题,我检查了eventId而不是列表中的位置来确定所点击的事件的位置,但这仍然存在上述问题。
应该的行为:
- 用户点击事件,视图展开到全屏状态 - 用户点击已展开的事件,视图回缩到原始大小 - 当另一个事件已经展开时,用户点击事件,展开的事件返回原始高度,并将点击的事件扩大到全屏状态
当前的行为:
- 用户点击事件,除了列表中的最后一项之外,所有视图都会正确展开 - 用户点击已展开的事件,视图会回缩但没有动画效果 - 当另一个事件已经展开时,用户点击事件,展开的事件回缩并且点击的事件正确扩大到全屏状态 - 用户点击列表中的最后一个事件,该事件会消失(可能已经缩小到小于0)
我知道这可能与recyclerview在屏幕上不可见时如何重用其视图的方式有关。为了解决此问题,我检查了eventId而不是列表中的位置来确定所点击的事件的位置,但这仍然存在上述问题。
public class EventRecyclerAdapter extends RecyclerView.Adapter<EventRecyclerAdapter.ViewHolder> {
private Context c;
private List<Event> items = new ArrayList<>();
private RelativeLayout container;
private int screenheight;
private EventListFragment eventListFragment;
private int expandedPosition = -1;
private static final String TAG = "EventRecyclerAdapter";
public interface ItemClickedListener {
void itemClicked(int position);
}
private ItemClickedListener itemClickedListener;
public EventRecyclerAdapter(List<Event> itemlist, Context c, EventListFragment eventListFragment, ItemClickedListener listener) {
this.items = itemlist;
this.c = c;
this.eventListFragment = eventListFragment;
this.itemClickedListener = listener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, null);
WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenheight = size.y;
// Get the screen height from the device
Resources r = c.getResources();
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, r.getDisplayMetrics());
screenheight -= px;
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
Event event = items.get(position);
// - get data from your itemsData at this position
// - replace the contents of the view with that itemsData
viewHolder.tvName.setText(event.getName());
viewHolder.tvLocation.setText(event.getLocation().getName());
viewHolder.tvDate.setText(Helper.dateDoubleToString(event.getStartDate()));
viewHolder.tvTicketCount.setText(String.valueOf(event.getNumberOfTickets()));
viewHolder.background.setBackgroundColor(Color.GRAY);
viewHolder.eventId = event.getId();
// Load the background image
if (event.getEventImageId() != null) {
Picasso.with(c).load(Helper.imageUrlString(event.getEventImageId())).into(viewHolder.background);
ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
viewHolder.background.setColorFilter(filter);
}
// Check if the view needs to be expanded, collapsed or just drawn normally.
if (expandedPosition == event.getId()) {
if (event.expanded) {
collapseView(viewHolder, event);
} else if (!event.expanded) {
expandView(viewHolder, position, event);
}
} else {
setContainerHeight(viewHolder, event);
}
}
private void expandView(final EventRecyclerAdapter.ViewHolder viewHolder, final int pos, Event event) {
ResizeAnimation resizeAnimation = new ResizeAnimation(
viewHolder.container,
viewHolder.container.getHeight(),
screenheight
);
resizeAnimation.setDuration(Constants.ANIMATION_SPEED);
resizeAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
viewHolder.infoContainer.setVisibility(View.VISIBLE);
viewHolder.closeIcon.setVisibility(View.VISIBLE);
itemClickedListener.itemClicked(pos);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
viewHolder.itemView.startAnimation(resizeAnimation);
viewHolder.expanded = true;
event.expanded = true;
}
private void collapseView(final EventRecyclerAdapter.ViewHolder viewHolder, Event event) {
ResizeAnimation resizeAnimation = new ResizeAnimation(
viewHolder.container,
viewHolder.container.getHeight(),
getContainerCollapsedHeight()
);
resizeAnimation.setDuration(Constants.ANIMATION_SPEED);
viewHolder.infoContainer.setVisibility(View.INVISIBLE);
viewHolder.closeIcon.setVisibility(View.INVISIBLE);
viewHolder.itemView.startAnimation(resizeAnimation);
viewHolder.expanded = false;
event.expanded = false;
}
private void setContainerHeight(EventRecyclerAdapter.ViewHolder viewHolder, Event event) {
viewHolder.container.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getContainerCollapsedHeight()));
viewHolder.infoContainer.setVisibility(View.INVISIBLE);
viewHolder.closeIcon.setVisibility(View.INVISIBLE);
event.expanded = false;
viewHolder.expanded = false;
}
private int getContainerCollapsedHeight() {
int containerHeight;
// Define the item containers height
if (items.size() <= 3) {
containerHeight = screenheight / items.size();
} else {
containerHeight = screenheight / 3;
}
return containerHeight;
}
/**
* Clear all current data and swap add the new data list.
* The expanded position also gets reset
* @param events
*/
public void swap(List<Event> events) {
this.items.clear();
this.items.addAll(events);
this.expandedPosition = -1;
Log.v(TAG,"SWAP SIZE : " + items.size());
notifyDataSetChanged();
}
// inner class to hold a reference to each item of RecyclerView
class ViewHolder extends RecyclerView.ViewHolder {
public TextView tvLocation, tvDate, tvTicketCount;
public TextView tvName;
public ImageView background;
public View container;
public View infoContainer;
public TextView closeIcon;
public int eventId;
public boolean expanded = false;
public ViewHolder(final View itemLayoutView) {
super(itemLayoutView);
tvName = (TextView) itemLayoutView.findViewById(R.id.tvName);
tvLocation = (TextView) itemLayoutView.findViewById(R.id.tvLocation);
tvDate = (TextView) itemLayoutView.findViewById(R.id.tvDate);
background = (ImageView) itemLayoutView.findViewById(R.id.background);
tvTicketCount = (TextView) itemLayoutView.findViewById(R.id.ticket_count);
container = itemLayoutView.findViewById(R.id.list_item_container);
infoContainer = itemLayoutView.findViewById(R.id.info_container);
closeIcon = (TextView) itemLayoutView.findViewById(R.id.close_icon);
infoContainer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Activity mainActivity = (Activity) c;
FragmentManager fm = mainActivity.getFragmentManager();
//add
FragmentTransaction ft = fm.beginTransaction();
ft.setCustomAnimations(R.animator.slide_to_top, R.animator.slide_from_bottom);
ft.addToBackStack(ft.toString());
ft.add(R.id.content_frame, EventFragment.newInstance(items.get(getAdapterPosition())), Constants.EVENT_FRAGMENT_TAG);
//commit change
ft.commit();
}
});
container.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
expandedPosition = eventId;
notifyDataSetChanged();
}
});
}
}
// Return the size of your itemsData (invoked by the layout manager)
@Override
public int getItemCount() {
return items.size();
}
}
我认为当我点击列表中的最后一项时,它会以某种方式运行collapseView
方法,导致其高度低于0。但是我无法弄清楚这是为什么。
希望有人能够发现问题所在。