sta*_*ete 137 expand android android-layout recycler-adapter android-recyclerview
我想扩展/折叠我的recyclerView的项目,以显示更多信息.我想实现SlideExpandableListView的相同效果.
基本上在我的viewHolder中我有一个不可见的视图,我想做一个平滑的展开/折叠动画,而不是只将可见性设置为VISIBLE/GONE.我一次只需要一个项目进行扩展,如果有一个高程来显示该项目已被选中,那将会很酷.
它与新Android最近通话记录列表的效果相同.选项"CALL BACK"和"DETAILS"仅在选择项目时可见.
Hei*_*erg 186
请不要使用任何库来实现此效果,而是根据Google I/O 2016使用推荐的方法.在recyclerView的onBindViewHolder方法中执行以下操作:
final boolean isExpanded = position==mExpandedPosition;
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
holder.itemView.setActivated(isExpanded);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mExpandedPosition = isExpanded ? -1:position;
TransitionManager.beginDelayedTransition(recyclerView);
notifyDataSetChanged();
}
});
Run Code Online (Sandbox Code Playgroud)
对于您想要的炫酷效果,请将它们用作list_item属性:
android:background="@drawable/comment_background"
android:stateListAnimator="@animator/comment_selection"
Run Code Online (Sandbox Code Playgroud)
其中comment_background是:
<selector
xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize="true"
android:enterFadeDuration="@android:integer/config_shortAnimTime"
android:exitFadeDuration="@android:integer/config_shortAnimTime">
<item android:state_activated="true" android:drawable="@color/selected_comment_background" />
<item android:drawable="@color/comment_background" />
</selector>
Run Code Online (Sandbox Code Playgroud)
和comment_selection是:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true">
<objectAnimator
android:propertyName="translationZ"
android:valueTo="@dimen/z_card"
android:duration="2000"
android:interpolator="@android:interpolator/fast_out_slow_in" />
</item>
<item>
<objectAnimator
android:propertyName="translationZ"
android:valueTo="0dp"
android:duration="2000"
android:interpolator="@android:interpolator/fast_out_slow_in" />
</item>
</selector>
Run Code Online (Sandbox Code Playgroud)
Moj*_*osh 70
不是说这是最好的方法,但似乎对我有用.
完整代码可在以下位置找到:示例代码:https: //github.com/dbleicher/recyclerview-grid-quickreturn
首先,将展开的区域添加到单元格/项目布局中,并使封闭的单元格布局为animateLayoutChanges ="true".这将确保展开/折叠动画:
<LinearLayout
android:id="@+id/llCardBack"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:animateLayoutChanges="true"
android:padding="4dp"
android:orientation="vertical">
<TextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|fill_horizontal"
android:padding="10dp"
android:gravity="center"
android:background="@android:color/holo_green_dark"
android:text="This is a long title to show wrapping of text in the view."
android:textColor="@android:color/white"
android:textSize="16sp" />
<TextView
android:id="@+id/tvSubTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|fill_horizontal"
android:background="@android:color/holo_purple"
android:padding="6dp"
android:text="My subtitle..."
android:textColor="@android:color/white"
android:textSize="12sp" />
<LinearLayout
android:id="@+id/llExpandArea"
android:visibility="gone"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:text="Item One" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:text="Item Two" />
</LinearLayout>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
然后,使您的RV Adapter类实现View.OnClickListener,以便您可以对所单击的项目执行操作.添加一个int字段以保存一个展开视图的位置,并将其初始化为负值:
private int expandedPosition = -1;
Run Code Online (Sandbox Code Playgroud)
最后,实现ViewHolder,onBindViewHolder()方法并覆盖onClick()方法.如果它的位置等于"expandedPosition",你将在onBindViewHolder中展开视图,如果不是,则隐藏它.您在onClick侦听器中设置expandedPosition的值:
@Override
public void onBindViewHolder(RVAdapter.ViewHolder holder, int position) {
int colorIndex = randy.nextInt(bgColors.length);
holder.tvTitle.setText(mDataset.get(position));
holder.tvTitle.setBackgroundColor(bgColors[colorIndex]);
holder.tvSubTitle.setBackgroundColor(sbgColors[colorIndex]);
if (position == expandedPosition) {
holder.llExpandArea.setVisibility(View.VISIBLE);
} else {
holder.llExpandArea.setVisibility(View.GONE);
}
}
@Override
public void onClick(View view) {
ViewHolder holder = (ViewHolder) view.getTag();
String theString = mDataset.get(holder.getPosition());
// Check for an expanded view, collapse if you find one
if (expandedPosition >= 0) {
int prev = expandedPosition;
notifyItemChanged(prev);
}
// Set the current position to "expanded"
expandedPosition = holder.getPosition();
notifyItemChanged(expandedPosition);
Toast.makeText(mContext, "Clicked: "+theString, Toast.LENGTH_SHORT).show();
}
/**
* Create a ViewHolder to represent your cell layout
* and data element structure
*/
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView tvTitle;
TextView tvSubTitle;
LinearLayout llExpandArea;
public ViewHolder(View itemView) {
super(itemView);
tvTitle = (TextView) itemView.findViewById(R.id.tvTitle);
tvSubTitle = (TextView) itemView.findViewById(R.id.tvSubTitle);
llExpandArea = (LinearLayout) itemView.findViewById(R.id.llExpandArea);
}
}
Run Code Online (Sandbox Code Playgroud)
这应该一次只扩展一个项目,使用系统默认动画进行布局更改.至少它对我有用.希望能帮助到你.
Kir*_*eph 67
为此,只需要简单的线条并不复杂
在你的onBindViewHolder方法中添加以下代码
final boolean isExpanded = position==mExpandedPosition;
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
holder.itemView.setActivated(isExpanded);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mExpandedPosition = isExpanded ? -1:position;
notifyItemChanged(position);
}
});
Run Code Online (Sandbox Code Playgroud)
mExpandedPosition是一个初始化为-1的int全局变量
首先使用previousExpandedPosition = -1声明一个全局变量
然后
final boolean isExpanded = position==mExpandedPosition;
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
holder.itemView.setActivated(isExpanded);
if (isExpanded)
previousExpandedPosition = position;
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mExpandedPosition = isExpanded ? -1:position;
notifyItemChanged(previousExpandedPosition);
notifyItemChanged(position);
}
});
Run Code Online (Sandbox Code Playgroud)
完成!!! 简单而谦逊.. :)
Lau*_*nac 15
有一个非常简单的库使用gradle支持:https://github.com/cachapa/ExpandableLayout.
直接来自图书馆文档:
<net.cachapa.expandablelayout.ExpandableLinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:el_duration="1000"
app:el_expanded="true">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Click here to toggle expansion" />
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="Fixed height"
app:layout_expandable="true" />
</net.cachapa.expandablelayout.ExpandableLinearLayout>
Run Code Online (Sandbox Code Playgroud)
当你标记你的扩张的观点,只是调用任何容器上这些方法:expand()
,collapse()
或toggle()
小智 8
我知道自原始问题发布以来已经很长时间了.但我认为对于像我这样缓慢的人来说,@ Heisenberg的回答会有所帮助.
在适配器类中声明两个变量as
private int mExpandedPosition= -1;
private RecyclerView recyclerView = null;
Run Code Online (Sandbox Code Playgroud)
然后在onBindViewHolder中跟随原始答案中给出的内容.
// This line checks if the item displayed on screen
// was expanded or not (Remembering the fact that Recycler View )
// reuses views so onBindViewHolder will be called for all
// items visible on screen.
final boolean isExpanded = position==mExpandedPosition;
//This line hides or shows the layout in question
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
// I do not know what the heck this is :)
holder.itemView.setActivated(isExpanded);
// Click event for each item (itemView is an in-built variable of holder class)
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// if the clicked item is already expaned then return -1
//else return the position (this works with notifyDatasetchanged )
mExpandedPosition = isExpanded ? -1:position;
// fancy animations can skip if like
TransitionManager.beginDelayedTransition(recyclerView);
//This will call the onBindViewHolder for all the itemViews on Screen
notifyDataSetChanged();
}
});
Run Code Online (Sandbox Code Playgroud)
最后,在适配器覆盖中获取recyclerView对象
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
this.recyclerView = recyclerView;
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
根本不需要使用第三方库.一个小调整的方法证明了谷歌I/O 2016和海森堡关于这一主题,做的伎俩.
由于notifyDataSetChanged()
重绘完整RecyclerView
,notifyDataItemChanged()
是一个更好的选择(不是最好的)因为我们有位置和我们可以使用ViewHolder
,并且notifyDataItemChanged()
只重绘特定ViewHolder
位置的特定.
但问题是ViewHolder
即使notifyDataItemChanged()
使用了咔嗒声和它的出现的过早消失也没有消除.
以下代码不依赖于notifyDataSetChanged()
或者notifyDataItemChanged()
在API 23上进行测试,并且在RecyclerView上使用时就像魅力一样,其中每个ViewHolder都有一个CardView
根元素:
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final boolean visibility = holder.details.getVisibility()==View.VISIBLE;
if (!visibility)
{
holder.itemView.setActivated(true);
holder.details.setVisibility(View.VISIBLE);
if (prev_expanded!=-1 && prev_expanded!=position)
{
recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.setActivated(false);
recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.findViewById(R.id.cpl_details).setVisibility(View.GONE);
}
prev_expanded = position;
}
else
{
holder.itemView.setActivated(false);
holder.details.setVisibility(View.GONE);
}
TransitionManager.beginDelayedTransition(recycler);
}
});
Run Code Online (Sandbox Code Playgroud)
prev_position
是一个初始化为-1的全局整数.
details
是展开时显示的完整视图,折叠时显示隐形.
如上所述,根元素ViewHolder
是一个CardView
with foreground
和stateListAnimator
属性,完全按照海森堡关于这个主题所说的那样定义.
更新:如果其中一个扩展,上述演示将折叠previosuly扩展项目.要修改此行为并保持扩展项目,即使展开另一个项目,您还需要以下代码.
if (row.details.getVisibility()!=View.VISIBLE)
{
row.details.setVisibility(View.VISIBLE);
row.root.setActivated(true);
row.details.animate().alpha(1).setStartDelay(500);
}
else
{
row.root.setActivated(false);
row.details.setVisibility(View.GONE);
row.details.setAlpha(0);
}
TransitionManager.beginDelayedTransition(recycler);
Run Code Online (Sandbox Code Playgroud)
更新:扩展列表中的最后一项时,可能无法使其完全可见,因为展开的部分位于屏幕下方.要获取屏幕中的完整项目,请使用以下代码.
LinearLayoutManager manager = (LinearLayoutManager) recycler.getLayoutManager();
int distance;
View first = recycler.getChildAt(0);
int height = first.getHeight();
int current = recycler.getChildAdapterPosition(first);
int p = Math.abs(position - current);
if (p > 5) distance = (p - (p - 5)) * height;
else distance = p * height;
manager.scrollToPositionWithOffset(position, distance);
Run Code Online (Sandbox Code Playgroud)
重要提示:要使上述演示工作,必须在其代码中保留RecyclerView及其LayoutManager的实例(后者的灵活性)
在使用建议的方法来实现驻留在RecyclerView上由HeisenBerg回答的RecyclerView展开/折叠项目RecyclerView
上的可扩展/可折叠项目之后,每当通过调用以及随后进行刷新时,我都看到了一些明显的工件。RecyclerView
TransitionManager.beginDelayedTransition(ViewGroup)
notifyDatasetChanged()
他的原始答案:
final boolean isExpanded = position==mExpandedPosition;
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
holder.itemView.setActivated(isExpanded);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mExpandedPosition = isExpanded ? -1 : position;
TransitionManager.beginDelayedTransition(recyclerView);
notifyDataSetChanged();
}
});
Run Code Online (Sandbox Code Playgroud)
改性:
final boolean isExpanded = position == mExpandedPosition;
holder.details.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
holder.view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mExpandedHolder != null) {
mExpandedHolder.details.setVisibility(View.GONE);
notifyItemChanged(mExpandedPosition);
}
mExpandedPosition = isExpanded ? -1 : holder.getAdapterPosition();
mExpandedHolder = isExpanded ? null : holder;
notifyItemChanged(holder.getAdapterPosition());
}
}
Run Code Online (Sandbox Code Playgroud)
int
跟踪扩展项的ViewHolder
项目崩溃时使用请注意,方法TransitionManager.beginDelayedTransition(ViewGroup)
和notifyDataSetChanged()
被替换notifyItemChanged(int)
为针对特定项目和一些小调整。
修改后,以前的不良影响应该消失了。但是,这可能不是完美的解决方案。它只做了我想要的,消除了眼神。
::编辑::
为了澄清起见,mExpandedPosition
和mExpandedHolder
均为全局变量。
归档时间: |
|
查看次数: |
136992 次 |
最近记录: |