android - simple - 안드로이드:RecyclerView 내용 스크롤 후 엉망진창



git android recyclerview (4)

RecyclerView를 사용하여 마크 목록을 표시하고 값의 각 표시를 CardView로 표시합니다. 그러나 카드의 일부 내용은 아래의 두 스크린 샷과 같이 RecyclerView를 아래로 스크롤 한 다음 뒤로 스크롤하면 사라집니다. 빨간색 직사각형의 내용은 스크롤 한 후에 손실됩니다.

스 크롤 링하기 전에;

스 크롤 링 후;

그것이 RecyclerView의 버그인지 아닌지 궁금하네요. 검색 후 아무런 해결책도 찾지 못했습니다.

모든보기는 제목을 제외한 모든 표시가 보이지 않으며 표시 여부는 표시 값에 따라 다릅니다.

아무도 왜 이런 일이 일어날 지 알고 있습니까?

https://src-bin.com


Answer #1

onBindHolder는 Recycler View가 새로운보기가 아니라면보기가 필요하기 때문에 여러 번 호출되었습니다. 따라서 하위 뷰에서 가시성을 설정할 때마다 다른 뷰 상태도 변경됩니다.

위아래로 스크롤 할 때마다 이러한보기가 잘못된 가시성 옵션으로 다시 표시되므로 항상 재활용 도구보기가 위젯의 이전 상태 / 조건 / 값을 알 수없는 두 조건을 모두 지정하십시오.

해결책 :

If 블록에서 모든 android widget.setVisibility (View.Gone)의 가시성을 설정하면 else 블록에서 위의 문제를 극복하기 위해 widget.setVisibility (View.Visible)와 반대되는 가시성을 설정해야합니다.

 @Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {

    viewHolder.tvName.setText(ModelCategoryProducts.name.get(i));
    viewHolder.tvPrice.setText("Rs."+String.format("%.2f", Float.parseFloat(ModelCategoryProducts.price.get(i))));
    if(ModelCategoryProducts.special_price.get(i).equals("null")) {
        viewHolder.tvSpecialPrice.setVisibility(View.GONE); // here visibility is gone and in else it's opposite visibility i set.
        viewHolder.tvPrice.setTextColor(Color.parseColor("#ff0000"));
        viewHolder.tvPrice.setPaintFlags(0);// here paint flag is 0 and in else it's opposite flag that i want is set.
    }else if(!ModelCategoryProducts.special_price.get(i).equals("null")){
        viewHolder.tvPrice.setTextColor(Color.parseColor("#E0E0E0"));
        viewHolder.tvSpecialPrice.setVisibility(View.VISIBLE);
        viewHolder.tvSpecialPrice.setText("Rs." + String.format("%.2f", Float.parseFloat(ModelCategoryProducts.special_price.get(i))));
        viewHolder.tvPrice.setPaintFlags(viewHolder.tvPrice.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
    }
    if (!ModelCategoryProducts.image_url.get(i).isEmpty()) {
        Picasso.with(context)
                .load(ModelCategoryProducts.image_url.get(i))
                .into(viewHolder.ivProduct);
    }

    viewHolder.setClickListener(new ItemClickListener() {
        @Override
        public void onClick(View view, int position, boolean isLongClick) {
            if (isLongClick) {
//                    Toast.makeText(context, "#" + position + " - " + ModelCategoryProducts.name.get(position) + " (Long click)", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(context, "#" + position + " - " + ModelCategoryProducts.name.get(position), Toast.LENGTH_SHORT).show();
                Intent i = new Intent(context, ProductDetail.class);
                i.putExtra("position",position);
                i.putExtra("flagHlvCheck", 5);
                context.startActivity(i);
            }
        }
    });
}

Answer #2

뷰 유형이 변경된 경우 새 뷰가없는 한 리사이클 러가 뷰를 필요로하므로 onBindHolder가 여러 번 호출되었습니다. 따라서 하위 뷰에서 가시성을 설정할 때마다 다른 뷰 상태도 변경됩니다.

위아래로 스크롤 할 때마다 이러한보기가 잘못된 가시성 옵션으로 다시 표시됩니다.

해결책 :

setValue 메소드가 값을 확인하고보기로 설정했습니다. 필요한 경우 다른 메소드 "showView"를 호출합니다. else 문 (값은 0 또는 null)과 hideView를 구현해야합니다.

void setValue(Object value, TextView textView, TableRow row, View seperator) {
    if (value != null) {
        if (!isEmpty(value.toString())) {
            textView.setText(String.valueOf(value));
            showViews(row, seperator);
        }
    } else
        hideViews(row, seperator);
}

private void showViews(TableRow row, View seperator) {
    row.setVisibility(View.VISIBLE);
    seperator.setVisibility(View.VISIBLE);
}

private void hideViews(TableRow row, View seperator) {
    row.setVisibility(View.INVISIBLE); // if there is a empty space change it with View.GONE
    seperator.setVisibility(View.INVISIBLE);
}

Answer #3

이 같은 문제로 약 24 시간 동안 싸우고 나에게 도움이되는 해결책을 찾았습니다. 열쇠는 RecyclerView.ViewHolder 클래스의 setIsRecyclable() 메소드를 사용하고 setIsRecyclable() .

여기에 내 onBindViewHolder() 코드의 섹션이 있습니다.

@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
    final DataSource dataSource = dataSourceList.get(position);

    holder.setIsRecyclable(false);

    holder.name.setText(dataSource.getName());
    holder.active.setChecked(dataSource.getActive());

    String logoStr = dataSource.getLogo();

    //Logo
    /**
     * Do all the logo insertion stunts here
     */
    /**
     * Register the changes to the Switch
     */
    holder.active.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){
            dataSource.setActive(isChecked);
        }
    });
}

Answer #4

이는 스크롤이 발생할 때 뷰가 다시 사용되기 때문입니다. 이 문제를 해결하려면 다른 셀 (예 : YUZME)에서 볼 수있는보기를 재설정해야합니다.

setValue (Object 값, TextView textView, TableRow 행, View seperator) 내에서 단순히 모든 txtVize *를 다시 숨 깁니다.

Recycler보기는 3 개의보기로 시작됩니다.

[0] FIZ104

[1] MAT102

[2] REK361

뷰가 아래쪽 뷰로 스크롤되면 [0]과 [1]이 재활용됩니다. 상위 뷰로 다시 스크롤하면 [2]는 FIZ104 및 MAT102에 포함 된 데이터를 표시하는 데 사용되며 REK361에 대한 변경 사항은 그대로 유지됩니다.





android-viewholder