【问题标题】:How to get Layout width modified in RecyclerView如何在 RecyclerView 中修改布局宽度
【发布时间】:2016-04-15 10:32:36
【问题描述】:

我在使用带有一些侦听器的布局的 RecyclerView 时遇到了困难。

代码是这样的

  • ViewHolder

     public static class ViewHolder extends RecyclerView.ViewHolder {
    
        public TextView tickerSymbol;
        public TextView companyName;
        public View highlightBuy;
        public LinearLayout categoryImage;
        public LayoutParams categoryLayoutParams;
        public LinearLayout arrowImage;
        public ImageView categoryIconSeparator;
        public ImageView arrowSeparator;
        public ImageView arrowIcon;
        public RelativeLayout stockRow;
        public LinearLayout tickerInfo;
        public Boolean isCategoryOpened = false;
    
        public ViewHolder(View itemView) {
            super(itemView);
            this.tickerSymbol = (TextView) itemView.findViewById(R.id.ticker_symbol_textview);
            this.companyName = (TextView) itemView.findViewById(R.id.company_name_textview);
            this.highlightBuy = itemView.findViewById(R.id.highlight_buy_view);
            this.categoryImage = (LinearLayout) itemView.findViewById(R.id.category_image);
            this.categoryLayoutParams = (LayoutParams) categoryImage.getLayoutParams();
            this.arrowImage = (LinearLayout) itemView.findViewById(R.id.arrow);
            this.categoryIconSeparator = (ImageView) itemView.findViewById(R.id.category_icon_separator);
            this.arrowSeparator = (ImageView) itemView.findViewById(R.id.arrow_separator);
            this.arrowIcon = (ImageView) itemView.findViewById(R.id.arrow_icon_imageview);
            this.stockRow = (RelativeLayout) itemView.findViewById(R.id.stock_row);
            this.tickerInfo = (LinearLayout) itemView.findViewById(R.id.ticker_info);
        }
    }
    
  • onCreateViewHolder

    @Override
    public StockListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    
      Context context = parent.getContext();
      LayoutInflater inflater = LayoutInflater.from(context);
    
      View stockView = inflater.inflate(R.layout.stock_list_row, parent, false);
    
      return new StockListAdapter.ViewHolder(stockView);
    }
    
  • onBindViewHolder

    @Override
    public void onBindViewHolder(final StockListAdapter.ViewHolder holder, final int position) {
      final Stock stock = mStocks.get(position);
      final int collapsedCategoryWidth = (int) mContext.getResources().getDimension(R.dimen.collapsed_category_icon_width);
      final int stockRowHeight = (int) mContext.getResources().getDimension(R.dimen.stock_row_height);
    
      //Reset holder status
      if (holder.isCategoryOpened) {
          holder.isCategoryOpened = false;
          holder.categoryImage.getLayoutParams().width = collapsedCategoryWidth;
          holder.categoryImage.setLayoutParams(holder.categoryImage.getLayoutParams());
          holder.arrowIcon.setRotationY(0);
      }
    
      holder.tickerSymbol.setText(stock.ticker);
    
      holder.companyName.setText(stock.name);
      holder.companyName.setSelected(true);
      holder.companyName.requestFocus();
    
      holder.categoryImage.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
    
            final int newWidth;
            final int startWidth;
            final int startArrowAngle;
            final int newArrowAngle;
    
            if (!holder.isCategoryOpened) {
                holder.isCategoryOpened = true;
                newWidth = holder.stockRow.getWidth() - holder.categoryLayoutParams.leftMargin - holder.arrowImage.getWidth() - ((LayoutParams) holder.arrowImage.getLayoutParams()).rightMargin - holder.categoryIconSeparator.getWidth();
                startWidth = collapsedCategoryWidth;
                startArrowAngle = 0;
                newArrowAngle = 180;
            } else {
                holder.isCategoryOpened = false;
                newWidth = collapsedCategoryWidth;
                startWidth = holder.categoryImage.getWidth();
                startArrowAngle = 180;
                newArrowAngle = 0;
            }
    
            Animation a = new Animation() {
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) {
                    holder.categoryLayoutParams.width = startWidth + (int) ((newWidth - startWidth) * interpolatedTime);
                    //MAYBE PROBLEM HERE??
                    holder.categoryImage.setLayoutParams(holder.categoryLayoutParams);
                    holder.arrowIcon.setRotationY(startArrowAngle + (newArrowAngle - startArrowAngle) * interpolatedTime);
                }
            };
            a.setDuration(500);
            holder.categoryImage.startAnimation(a);
        }
    });
    

我将附上我的错误示​​例。

当我第一次单击一个视图时,onClick 工作成功,但如果我滚动然后返回该视图,只有箭头被翻转(这意味着 onClick 被调用)但 LinearLayout Width 不会被修改。

但现在真正奇怪的是,如果我点击另一个以前没有点击过的视图,或者(我猜)没有被回收,会发生以下情况:

所以我猜,宽度已设置,但未显示。

我真的不知道如何解决这个问题。

感谢您的帮助或其他想法!

这是我已经尝试过的:

  • 将状态放入库存中;
  • 将监听器置于适配器之外;
  • 将监听器放入支架内;

【问题讨论】:

    标签: java android android-recyclerview


    【解决方案1】:

    如果您已经点击了该商品,请在您的商店类中添加 1 个变量来存储值。

    这样的例子,我在 store 中设置了变量 isSelected:

     private boolean mSelected=false;
    
     public boolean getIsSelected(){
            return this.mSelected;
        }
        public void setIsSelected(boolean mSelected){
            this.mSelected=mSelected;
        }
    

    然后在您的 onClick 方法中,只需在 if 条件后添加 stock.setIsSelected(!stock.getIsSelected()) 并将您的 if 条件设置为从 stock.getIsSelected() 读取布尔值,最后,只需从您的持有人中删除变量 isCategoryOpened。

    public void onClick(View v) {
    
            final int newWidth;
            final int startWidth;
            final int startArrowAngle;
            final int newArrowAngle;
    
            if (stock.getIsSelected()) {
                newWidth = holder.stockRow.getWidth() - holder.categoryLayoutParams.leftMargin - holder.arrowImage.getWidth() - ((LayoutParams) holder.arrowImage.getLayoutParams()).rightMargin - holder.categoryIconSeparator.getWidth();
                startWidth = collapsedCategoryWidth;
                startArrowAngle = 0;
                newArrowAngle = 180;
            } else {
                newWidth = collapsedCategoryWidth;
                startWidth = holder.categoryImage.getWidth();
                startArrowAngle = 180;
                newArrowAngle = 0;
            }
           stock.setIsSelected(!stock.getIsSelected())
            Animation a = new Animation() {
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) {
                    holder.categoryLayoutParams.width = startWidth + (int) ((newWidth - startWidth) * interpolatedTime);
                    //MAYBE PROBLEM HERE??
                    holder.categoryImage.setLayoutParams(holder.categoryLayoutParams);
                    holder.arrowIcon.setRotationY(startArrowAngle + (newArrowAngle - startArrowAngle) * interpolatedTime);
                }
            };
            a.setDuration(500);
            holder.categoryImage.startAnimation(a);
        }
    

    如果我错了,请纠正我:)

    【讨论】:

    • 为什么要将仓位转给股票?我应该在列表中使用它...股票对象是使用该位置从我的数据中获取的
    • +1。这是我可能会选择的方式。保存项目的内部状态是这种情况下最简单(也是最干净)的解决方案。 RecyclerView 将获取不再可见的项目(例如在滚动之后)并将它们“回收”以获取新项目。常见的情况是上下滚动,因为有些项目在一端消失,而另一些在另一端变得可见。
    • 我试过了,但还是一样 :( 我猜是一个绑定到宽度设置的 Android 错误
    • 我试过了,但是更糟,现在视图被克隆了,没有恢复
    【解决方案2】:

    问题已解决,导致所有这些故障的原因是我调用 holder.companyName.requestFocus() 以使选取框在 TextView 中工作。

    结果表明我不需要requestFocus() 来让它工作,这是问题的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多