我正在尝试在我的应用中实现滑动功能。滑动功能本身运行良好。但是,应用程序默认显示背景视图(有点像刮刮而获胜),请看一下:
(http://i.imgur.com/NTGcguT.png)
我尝试在XML中将foreground
和background
转换为几乎无处不在,同时在java中引用它们,在onChildDraw
,onChildDrawOver
内以及所有其他方法,但没有运气。
一旦我触摸卡进行滑动,该功能就能正常工作(图中的卡2)。如果我松开滑动并将卡片恢复到默认位置,它将正常工作(图片中的卡片3和5)。再次创建活动后,所有卡片都会进入默认的蓝色背景(图片中的1,4和6张卡片)
编辑:顺便说一句,卡片x,y,z指的是他们在屏幕上的位置而不是他们的内容,只是因为我尝试尽可能快地让他们继续测试< / p>以下是我的相关代码:
XML文件:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:clickable="true"
android:focusable="true"
android:descendantFocusability="blocksDescendants"
>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_margin="0dp"
card_view:cardCornerRadius="10dp"
card_view:cardElevation="5dp"
android:layout_height="match_parent"
android:longClickable="true"
android:contextClickable="true">
<RelativeLayout
android:id="@+id/view_foreground"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Foreground elements here-->
</RelativeLayout>
<RelativeLayout
android:id="@+id/view_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
>
<!--Background elements here-->
</RelativeLayout>
</android.support.v7.widget.CardView>
</FrameLayout>
MyHolder.JAVA中定义了:
public RelativeLayout viewBackground, viewForeground;
...
viewBackground = (RelativeLayout)itemView.findViewById(R.id.view_background);
viewForeground = (RelativeLayout)itemView.findViewById(R.id.view_foreground);
delTxt = (TextView) itemView.findViewById(R.id.delBackground);
这是家庭活动(你在截图中看到的那个):
ItemTouchHelper.SimpleCallback simpleItemTouchCallback =
new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
@Override
public boolean onMove(RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
//some stuff
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder
viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
final View foregroundView = ((MyHolder)viewHolder).viewForeground;
drawBackground(viewHolder, dX, actionState);
if (viewHolder.getAdapterPosition() == -1) {
return;
}
getDefaultUIUtil().onDraw(c, recyclerView, foregroundView, dX, dY,
actionState, isCurrentlyActive);
}
@Override
public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder, float dX, float dY,
int actionState, boolean isCurrentlyActive) {
final View foregroundView = ((MyHolder)viewHolder).viewForeground;
drawBackground(viewHolder, dX, actionState);
getDefaultUIUtil().onDrawOver(c, recyclerView, foregroundView, dX, dY,
actionState, isCurrentlyActive);
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder){
final View backgroundView = ((MyHolder)viewHolder).viewBackground;
final View foregroundView = ((MyHolder)viewHolder).viewForeground;
backgroundView.setRight(0);
getDefaultUIUtil().clearView(foregroundView);
}
private void drawBackground(RecyclerView.ViewHolder viewHolder, float dX,
int actionState) {
final View backgroundView = ((MyHolder)viewHolder).viewBackground;
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
//noinspection NumericCastThatLosesPrecision
backgroundView.setRight((int) Math.max(dX, 0));
}
}
编辑:找到解决方案,我只是翻转了XML文件中的背景和前景,所以前景变为第二,然后为前景提供了白色背景色。
答案 0 :(得分:0)
此问题可能是由RecyclerView.notifyDatasetChange()
或RecyclerView
无效引起的。当RecyclerView
的UI更新时,它可能会创建新的ViewHolder
,其视图将成为默认视图。或者当默认ViewHolder
(例如:你的照片中的卡片6)被回收并在位置1(图片中的卡片2)中重复使用时,也会导致您的问题。
因此,您应该在手势回调中保存查看状态,并在Adapter.onBindViewHolder()
答案 1 :(得分:0)
我在下面写了一个演示。如果不编写代码来恢复自定义视图,则滚动RecyclerView
时自定义视图的行为可能会出错。
RecyclerViewActivity:
public class RecyclerViewActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private Adapter mAdapter;
private List<ViewStatus> mViewStatuses;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_view);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
initData();
initAdapter();
LinearLayoutManager manager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(manager);
}
private void initData() {
mViewStatuses = new ArrayList<>();
int i = 0;
while (i < 100) {
ViewStatus temp = new ViewStatus();
temp.isBeanTouched = false;
temp.text = String.valueOf(i);
mViewStatuses.add(temp);
i++;
}
}
private void initAdapter() {
mAdapter = new Adapter();
mRecyclerView.setAdapter(mAdapter);
}
class Adapter extends RecyclerView.Adapter<ViewHolder> {
LayoutInflater mInflater = LayoutInflater.from(RecyclerViewActivity.this);
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View holderView = mInflater.inflate(R.layout.item_recycler_view, parent, false);
return new ViewHolder(holderView);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.onBind(position);
}
public ViewStatus getItem(int position) {
return mViewStatuses.get(position);
}
@Override
public int getItemCount() {
return mViewStatuses.size();
}
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView currentPosTv;
TextView prePosTv;
CustomView mCustomView;
ViewStatus mViewStatus;
public ViewHolder(View itemView) {
super(itemView);
currentPosTv = (TextView) itemView.findViewById(R.id.tv_current_pos);
prePosTv = (TextView) itemView.findViewById(R.id.tv_pre_pos);
mCustomView = (CustomView) itemView.findViewById(R.id.custom_view);
}
public void onBind(int position) {
mViewStatus = mAdapter.getItem(position);
// if holder is recycled and reused, then save the pre position in prePosTv
prePosTv.setText("pre position: " + currentPosTv.getText());
currentPosTv.setText("current position: " + mViewStatus.text);
itemView.setOnClickListener(this);
//if do not add code blow to resume customView, then the customView's behavior may be wrong when scroll RecyclerView
// mCustomView.setSelect(mViewStatus.isBeanTouched);
}
@Override
public void onClick(View v) {
//save the view status
mViewStatus.isBeanTouched = !mViewStatus.isBeanTouched;
mCustomView.setSelect(mViewStatus.isBeanTouched);
}
}
class ViewStatus {
boolean isBeanTouched = false;
String text = "";
}
}
CustomView:
public class CustomView extends View {
public CustomView(Context context) {
super(context);
}
public CustomView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void setSelect(boolean select) {
if (select) {
setBackgroundColor(Color.RED);
} else {
setBackgroundColor(Color.WHITE);
}
}
}
activity_recycler_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
item_recycler_view
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:paddingLeft="8dp">
<com.example.lemon.recyclerviewreuse.CustomView
android:id="@+id/custom_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/tv_current_pos"
android:layout_alignBottom="@+id/tv_pre_pos"/>
<TextView
android:id="@+id/tv_current_pos"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="current position:1"/>
<TextView
android:id="@+id/tv_pre_pos"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="pre position: 0"
android:layout_below="@id/tv_current_pos"/>
</RelativeLayout>