背景视图在滑动功能中默认显示

时间:2018-02-22 01:42:01

标签: java android swipe

我正在尝试在我的应用中实现滑动功能。滑动功能本身运行良好。但是,应用程序默认显示背景视图(有点像刮刮而获胜),请看一下:

http://i.imgur.com/NTGcguT.png

我尝试在XML中将foregroundbackground转换为几乎无处不在,同时在java中引用它们,在onChildDrawonChildDrawOver内以及所有其他方法,但没有运气。

一旦我触摸卡进行滑动,该功能就能正常工作(图中的卡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文件中的背景和前景,所以前景变为第二,然后为前景提供了白色背景色。

2 个答案:

答案 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>