【问题标题】:android recyclerview setVisibility View.GONE still occupies spaceandroid recyclerview setVisibility View.GONE 仍然占用空间
【发布时间】:2018-02-26 20:01:17
【问题描述】:

我只想在我的回收站视图中列出不喜欢的项目。我在 MainActivity 的 rv 中有完整的项目列表(此处未设置可见性)。我可以通过单击图像按钮来设置喜欢或不喜欢的每个项目。 MainActivity 显示显示图像按钮喜欢与否的项目(卡片视图)的完整列表。如果 item 被喜欢,它会作为单独的条目存储在 firebase db 中,在带有 item 键(firebase key .push)的 Likes 下,而不是在 Items 下。 (在 firebase 数据库中,我有用户、项目、喜欢)。

这是我的子活动代码 DislikedItemsActivity,我想通过使用 setVisibility(View.GONE) 仅显示不喜欢的项目来显示喜欢的项目。这仍然保留了 View.GONE 项目之间的空间(尽管这些卡片视图是空的)。

mRecyclerView = (RecyclerView) findViewById(R.id.rvItemList);
mRecyclerView .setHasFixedSize(true);

final LinearLayoutManager linearLayoutManager = new 
LinearLayoutManager(this);
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true); 

mRecyclerView.setLayoutManager(linearLayoutManager);

final FirebaseRecyclerAdapter<Item, MainActivity.ItemViewHolder> 
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Item, 
MainActivity.ItemViewHolder>(
            Item.class,
            R.layout.list_item,
            MainActivity.ItemViewHolder.class,
            mDatabase

    ) {
        @Override
        protected void populateViewHolder(final MainActivity.ItemViewHolder viewHolder, final Item model, final int position) {

            final String itemKey = getRef(position).getKey();

            mDatabaseItemsLiked.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {

        // if item is not liked, thus no user set in db ( I want to see only items that are liked in my recyclerview)
                    if (!dataSnapshot.child(itemKey).hasChild(mAuth.getCurrentUser().getUid())) {

                        viewHolder.mView.setVisibility(View.VISIBLE);

                        viewHolder.itemNameSetup(model.getItemName());
                        viewHolder.mView.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {

                                Intent itemSheetIntent = new Intent(DislikedItemsActivity.this, ItemSheetActivity.class);
                                adatlapIntent.putExtra("item_key", itemKey);
                                startActivity(itemSheetIntent);
                            }
                        });

                    } else {

                        viewHolder.mView.setVisibility(View.GONE);

                        mRecyclerView.getAdapter().notifyItemRemoved(position); //this puts together the visible items, but when scrolling, it gets messed up

        }

                }

                @Override
                public void onCancelled(DatabaseError databaseError) {
                    Log.e(TAG, databaseError.toString());
                }
            });
        }

        @Override
        public void onBindViewHolder(MainActivity.TermekViewHolder viewHolder, int position) {
            super.onBindViewHolder(viewHolder, position);

        }
    };
    mRecyclerView.setAdapter(firebaseRecyclerAdapter);
}

我寻找了许多解决方案,例如 onBindViewHolder、notifyDataChanged、将边距设置为 0、将 xml 中的布局大小设置为 wrap_content。我能得到的最好的方法是使用 mRecyclerView.getAdapter().notifyItemRemoved(position); 让不喜欢的项目没有空格,但是向后滚动列表整个 rv 会变得混乱(重复条目、空格、无序列表)。

我不知道如何在新活动中仅列出 MainActivity rv 的完整项目列表中不喜欢的项目?我上面的代码只显示不喜欢的项目,但只有在我滚动到列表末尾之前,如果我向后滚动,rv 就会搞砸。我在 onBindViewHolder 中记录了视图 (18items) 的位置,首先它按顺序计算所有项目 (17,16,15,14...0),但是从列表末尾滚动到向后,位置从 0 跳到 4 就像 7 次(总是改变多少次)然后项目 5,6 相同,直到项目 17(它们的所有位置在滚动期间显示在 onBindViewHolder 7 或 8 次,即 5,5,5,5,6,6,6 ,6) 并且仅用于向后滚动和向后移动期间 rv 仅显示不喜欢的项目或空视图或不喜欢的项目的重复条目。

我的 xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="@drawable/hatter"
tools:context="com.example.user.itemlist.ItemsLikedActivity">

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rvItemList"
    >
</android.support.v7.widget.RecyclerView>

(不知道如何添加图片)当不喜欢的列表出现时,它显示第一个项目(cardview占据全屏),当我开始滚动列表时(从1.可见项目到下一个可见项目)如果有空格(item1 vis 和 next vis item 是 4),重新排列,我可以看到下一个可见项目(item4)移动到 1.可见项目,然后列表的其余部分安排得很好,直到我开始向后滚动,然后它用空格和双重输入重新排列 rv。该列表来回移动直到两端(这是完整项目列表的长度,而不仅仅是不喜欢的项目),但可见项目都被弄乱了。

【问题讨论】:

  • 显示你的 xml 文件
  • 也分享截图
  • 真的不应该在 RecyclerView 的每一行中进行网络调用。您应该将数据下载到另一个类中,然后在下载后将其传递给适配器。或者过滤您已有的列表,然后将其传递给适配器。这样,您根本不需要将可见性设置为 GONE。
  • 更新了 xml 和截图描述
  • 对不起,我不明白你的建议-billynomates。我怎么知道其他用户是否喜欢我的项目,除非我从 db.xml 下载它。我正在使用firebase的离线功能并且应用程序离线工作,因此不喜欢或从喜欢变为不喜欢的项目出现在ItemsNotLikedActivity中(最初我写了ItemsLikedActivity,但它实际上是ItemsNotLiked)。它也会离线更改状态。滚动弄乱了列表。

标签: android android-recyclerview visibility cardview


【解决方案1】:

使用此代码删除占用的空间:

ViewGroup.LayoutParams params = holder.itemView.getLayoutParams();
params.height = 0;
holder.itemView.setLayoutParams(params);

【讨论】:

    【解决方案2】:

    我找到了过滤整个数据库的解决方案。在我的问题中,我只想在单独的活动中获得喜欢/不喜欢的项目,尽管我之前的代码显示了过滤的项目,但有差距。 在下面的代码中,我更改了 DatabaseReferences(具有完整项目列表的 mDatabase -node 和具有项目 uid 和用户 uid 的 mDatabaseItemsLiked -node)。

    这只给出了只有数字作为 likeItems 的空卡片,但是为了从 mDatabase(完整列表)中获取名称,我使用了 dataSnapshot.getValue(Item.class).getItemName()。

    firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Item, 
    MainActivity.ItemViewHolder>(
            Item.class,
            R.layout.list_item,
            MainActivity.ItemViewHolder.class,
            mDatabaseItemsLiked
    
    ) {
        @Override
        protected void populateViewHolder(final MainActivity.ItemViewHolder
                viewHolder, final Item model, final int position) {
    
            final String itemKey = getRef(position).getKey();
    
            mDatabase.child(itemKey).addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
    viewHolder.itemNameSetup(dataSnapshot.getValue(Item.class).getItemName());
    viewHolder.mView.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
    
                                Intent itemSheetIntent = new Intent(LikedItemsActivity.this, ItemSheetActivity.class);
                                adatlapIntent.putExtra("item_key", itemKey);
                                startActivity(itemSheetIntent);
                            }
                        });
    

    这对我来说没有任何问题。我希望它是网络高效的。

    【讨论】:

      【解决方案3】:

      您可以尝试将喜欢的项目存储在boolean array 和稍后在populateViewHolder 检查项目是否有like o no 并设置可见性。

      我愿意这样做:

      1. 在你的班级声明:

      private boolean [] itemLiked;

      1. 在您的构造函数中:

      this.itemLiked = new boolean [arrayOfAllItems.size]

      1. 点击事件:

      itemLiked[position] = true; //Where position is row position

      1. onBindViewholder 或在您的情况下为 populateViewHolder:

        如果 (!itemLiked[位置]) {
        viewHolder.mView.setVisibility(View.GONE); }

      希望对你有帮助,祝你好运!

      已编辑 我不完全了解您想要做什么,这就是为什么我将代码留给您两种情况。 案例 1. 标记和取消标记行。 案例 2. 保存到数据库或删除。

      继续完整代码

      Activity XML 添加RecyclerView:

      <android.support.v7.widget.RecyclerView
          android:id="@+id/my_rv"
          android:layout_width="match_parent"
          android:layout_height="match_parent"/>
      

      为行制作自定义布局:

      <TextView
          android:id="@+id/question_tv"
          android:layout_width="0dp"
          android:layout_height="wrap_content"
          android:layout_weight="5"
          android:text="QUESTION"/>
      
      <ImageButton
          android:id="@+id/like"
          android:layout_width="0dp"
          android:layout_height="wrap_content"
          android:layout_weight="1"
          android:src="@android:drawable/ic_input_add"
          android:background="@android:color/transparent"
          android:layout_marginRight="4dp"/>
      
      <ImageButton
          android:id="@+id/dislike"
          android:layout_width="0dp"
          android:layout_height="wrap_content"
          android:layout_weight="1"
          android:src="@android:drawable/ic_delete"
          android:background="@android:color/transparent"
          android:layout_marginRight="4dp"/>
      

      创建一个模型类:

      public class SomeModel {
          private String question;
      
          public SomeModel(String question) {
              this.question = question;
          }
          public String getQuestion() {
              return question;
          }
      }
      

      制作适配器类:

      public class SomeAdapter extends RecyclerView.Adapter {
      private ArrayList<SomeModel> arrayList;
      private boolean [] item_has_like, item_hase_vote;
      
      public SomeAdapter(ArrayList<SomeModel> arrayList) {
          this.arrayList = arrayList;
          this.item_has_like = new boolean[arrayList.size()];
          this.item_hase_vote = new boolean[arrayList.size()];
      }
      
      @Override
      public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
          MyViewHolder myViewHolder = null;
          LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
          View view = layoutInflater.inflate(R.layout.draw_row, parent, false);
          myViewHolder = new MyViewHolder(view);
          return myViewHolder;
      }
      
      @Override
      public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
      
          final MyViewHolder myViewHolder = (SomeAdapter.MyViewHolder)holder;
          final SomeModel item = arrayList.get(position);
          int backGround;
         /**In background you can save whateveryou need, example:
          * backGround= R.drawable.some_background;
          * backGround= View.GONE;
          *.....
          **/
      
          if (item_hase_vote[position]){
              if (item_has_like[position])
              {
                  backGround= Color.GREEN;// 
              } else {
                  backGround= Color.RED;
              }
          } else {
              backGround= Color.TRANSPARENT;
          }
          myViewHolder.questionTV.setText(item.getQuestion());
          myViewHolder.questionTV.setBackgroundColor(backGround);
      }
      @Override
      public int getItemCount() {
          return arrayList.size();
      }
      public class MyViewHolder extends RecyclerView.ViewHolder {
          private TextView questionTV;
          private ImageView like, dislike;
      
          public MyViewHolder(final View itemView) {
              super(itemView);
      
              questionTV = (TextView)itemView.findViewById(R.id.question_tv);
              like = (ImageView)itemView.findViewById(R.id.like);
              dislike = (ImageView)itemView.findViewById(R.id.dislike);
      
              like.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      //Item  been voted
                      item_hase_vote[getAdapterPosition()] = true;
                      //Item got Like save in boolean array by row position
                      item_has_like[getAdapterPosition()] = true;
                      //notify your adapter
                      notifyDataSetChanged();
                      /*OR Here comes the code where You save Item in Your Data Base.*/
                  }
              });
              dislike.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      //Item  been voted
                      item_hase_vote[getAdapterPosition()] = true;
                      // Item got DisLike save in boolean array by row position
                      item_has_like[getAdapterPosition()] = false;
                      //notify your adapter
                      notifyDataSetChanged();
      
                      /*OR Here You Remove item on Dislike
                      arrayList.remove(getAdapterPosition());
                      notifyItemRemoved(getAdapterPosition());
                      notifyItemRangeChanged(getAdapterPosition(),arrayList.size());
                      */
                  }
              });
          }
      }
      

      }

      还有你的活动:

      public class SomeActivity extends AppCompatActivity {
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_some);
      
          ArrayList<SomeModel> arrayList = new ArrayList<>();
          for (int i = 0; i <77 ; i++) {
              arrayList.add(new SomeModel("Question " + i));
          }
          RecyclerView recyclerView = (RecyclerView) findViewById(R.id.my_rv);
          SomeAdapter adapter = new SomeAdapter(arrayList);
          recyclerView.setAdapter(adapter);
          LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
          recyclerView.setLayoutManager(layoutManager);
      
      }
      

      }

      通过adapterPosition将选定的项目保存在布尔值、字符串、int....[]中,适配器总是会知道每个项目发生了什么,并且你的列表总是会被安排。

      祝你好运!

      【讨论】:

      • 我得到了与您的解决方案相同的结果。 view.gone 仅将其设置为不可见,空间仍然存在。我现在注意到只做 setvisibility 不会删除空间。当我将 notifyItemRemoved(position) 放入 populateViewHolder 时,其他方面
      • view.gone 仅将项目设置为不可见,空格仍然存在。我现在注意到只做 setvisibility 不会删除空间。当我将 notifyItemRemoved(position) 放在其他侧的 populateViewHolder 中时,rv 仅设置可见项目(即,在 18 个项目中,只有 5 个不喜欢的项目是可见的)没有空间,但在滚动到列表末尾之后(5 项)滚动停止我只能向后移动,这时一切都搞砸了,我现在可以向后滚动 18 项(有些是不可见的或重复的条目)。
      • 我无法编辑我的上一个。评论。我不知道如何将您推荐的构造器放入我的 Item 类中。我不知道如何在那里获得 arrayOfAllItems.size 。我在 ItemsNotLikeActivity.class 中进行了更改。我将您的构造函数放在 populateViewHolder 中,然后将 on click 放在 else 一侧。
      • @Zeghra 再次检查我的答案,希望它对你有用!
      • 您将位置保存在数组列表中并设置为可见的想法听起来真的很棒。我想要做的是,只有不喜欢 rv 中具有名称和图像按钮的卡片视图的项目(默认状态不喜欢)。如果按下此图像按钮,图像将变为喜欢。有一个显示所有项目的 rv,并在另一个仅显示不喜欢的项目的活动中拥有另一个 rv(如何?)。如果在 dislikeActivity 上按下 imagebutton(仅显示不喜欢的项目),则该项目也应该消失(因为它变得喜欢)。最好只过滤 rv 而不是通过网络从 db 下载查询。
      【解决方案4】:

      我也遇到了同样的问题。我的想法是,如果RelativeLayout 一个接一个地加载,height=0,规格就会被删除。所以它对我有用。

      这是我的 ViewHolder。我在这里介绍我的相关布局。

         public static class BlogViewHolder extends RecyclerView.ViewHolder {
                  View mView;
                  TextView txtdate;
                  RelativeLayout con_rel;
                  String name_day = "no name";
      
                  public BlogViewHolder(View itemView) {
                      super(itemView);
                      mView=itemView;
                      con_rel=(RelativeLayout)itemView.findViewById(R.id.con_rel);
                      txtdate = (TextView)itemView.findViewById(R.id.day);
                  }
          } 
      

      我设置了heightwidth

          con_ref=FirebaseDatabase.getInstance().getReference().child("/consultation");
      FirebaseRecyclerAdapter<Consultation,SelectConsaltation.BlogViewHolder>recyclerAdapter=new FirebaseRecyclerAdapter< Consultation,SelectConsaltation.BlogViewHolder>(
                          Consultation.class,
                          R.layout.consultation_card,
                          SelectConsaltation.BlogViewHolder.class,
                          con_ref
                  ) {
           @Override
                      protected void populateViewHolder(final SelectConsaltation.BlogViewHolder viewHolder, final Consultation model, final int Consultation) {
      
                          Shedule_ref.child(model.getScheduleID()).child("Day").addValueEventListener(new ValueEventListener() {
                             ViewGroup.LayoutParams params = viewHolder.con_rel.getLayoutParams();
                              @Override
                              public void onDataChange(DataSnapshot dataSnapshot) {
                                  name_day = dataSnapshot.getValue(String.class);
      
                                  if (doctor_id_from_doctor.equals( model.getDoctorID() )){
      
                                      SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
                                      Date strDate = null;
      
                                      try {
                                          strDate = sdf.parse(model.getDate());
                                      } catch (ParseException e) {
                                          e.printStackTrace();
                                      }
                                      if(System.currentTimeMillis()<=strDate.getTime() ) {
                                          params.height = 300;
                                          params.width =800;
                                          viewHolder.con_rel.setLayoutParams(params);
                                          viewHolder.setDate(model.getDate(),name_day);
                                      }
                                      else {
      
                                          **params.height = 0;
                                          params.width = 0;
                                          viewHolder.con_rel.setLayoutParams(params);**
                                      }
      
                                     }
                                  else {
                                      params.height = 0;
                                      params.width = 0;
                                      viewHolder.con_rel.setLayoutParams(params);
                                  }
                              }
      
                              @Override
                              public void onCancelled(DatabaseError databaseError) {
      
                              }
                          });
      
      
                      }
                  };
                  recyclerView.setAdapter(recyclerAdapter);
      
      
              }
      

      我的卡片查看代码

      <?xml version="1.0" encoding="utf-8"?>
      <RelativeLayout
          android:id="@+id/con_rel"
          android:layout_marginRight="10dp"
          android:layout_marginLeft="10dp"
          android:layout_marginTop="2dp"
          android:layout_marginBottom="3dp"
          xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
          android:layout_height="wrap_content" android:background="#a2ffffff">
          <LinearLayout
              android:layout_width="match_parent"
              android:layout_marginTop="3dp"
              android:layout_height="wrap_content"
              android:orientation="vertical">
      
              <TextView
                  android:id="@+id/day"
                  android:layout_marginTop="10dp"
                  android:textSize="18sp"
                  android:layout_marginLeft="5dp"
                  android:textColor="@color/colorBlack"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:text="@string/_07th_of_sunday_january_2018_at_9_00am"/>
              <TextView
                  android:id="@+id/nextnumber"
                  android:layout_marginLeft="5dp"
                  android:textSize="18sp"
                  android:textColor="@color/colornextnumber"
                  android:textStyle="bold"
                  android:layout_marginTop="20dp"
                  android:text="@string/next_avealable_number_is_04"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content" />
              <TextView
                  android:id="@+id/booknow"
                  android:textStyle="bold"
                  android:textSize="18sp"
                  android:layout_marginTop="20dp"
                  android:layout_marginLeft="240dp"
                  android:layout_marginBottom="10dp"
                  android:textColor="@color/colorbookNow"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:text="@string/book_now"/>
          </LinearLayout>
      </RelativeLayout>
      

      这是我的inreface

      【讨论】:

        猜你喜欢
        • 2015-12-18
        • 2016-08-31
        • 1970-01-01
        • 2017-04-13
        • 2016-03-31
        • 1970-01-01
        • 1970-01-01
        • 2019-08-02
        • 1970-01-01
        相关资源
        最近更新 更多