web-dev-qa-db-ja.com

水平RecyclerViewの下にドットを追加するにはどうすればよいですか?

私が望むように画像を表示するRecyclerViewがあります

    RecyclerView detailsRecycleImage = (RecyclerView) view.findViewById(R.id.detailsRcycleImage);
     RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(
      getActivity().getApplicationContext(),
      LinearLayoutManager.HORIZONTAL,
      false
    );

    detailsRecycleImage.setLayoutManager(mLayoutManager);
    ImagesAdapter imgAdapter = new 
    ImagesAdapter(getActivity(),contactsData.getContactImages());
    detailsRecycleImage.setAdapter(imgAdapter);  

そして私のアダプターコードは

     public class ImagesAdapter extends  RecyclerView.Adapter<ImagesAdapter.MyViewHolder>{
  private Context cnt;
  public ArrayList<String> imgsUrls;
  public ImagesAdapter(Context cnt, ArrayList<String> imgsUrls) {
    this.cnt=cnt;
    this.imgsUrls=imgsUrls;
  }

  @Override
  public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_img,parent,false);

    return new MyViewHolder(itemView);
  }

  @Override
  public void onBindViewHolder(final MyViewHolder holder, int position) {
    String singleImg = imgsUrls.get(position);
    Picasso.with(cnt).load(singleImg).into(holder.img);
  }

  @Override
  public int getItemCount() {
    return imgsUrls.size();
  }


  public class MyViewHolder extends RecyclerView.ViewHolder {
    public ImageView img;

    public MyViewHolder(View view) {
      super(view);
      img = (ImageView) view.findViewById(R.id.img);
    }
  }
}

そして私のレイアウトは

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content">

        <ImageView
          Android:layout_width="match_parent"
          Android:layout_height="wrap_content"
          Android:id="@+id/img"
          />
</RelativeLay

この画像のように、インジケータとしてrecyclerviewの下にドットを追加するだけです enter image description hereenter image description here
コードに何かを追加してこのビューを取得する方法はありますか?

11
ahmed saber

LinePagerIndicatorDecorationを少し変更してDotsIndicatorDecorationにし、GridLayoutManagerとLinearLayoutManagerの両方をサポートします

public class DotsIndicatorDecoration extends RecyclerView.ItemDecoration {

    private final int indicatorHeight;
    private final int indicatorItemPadding;
    private final int radius;

    private final Paint inactivePaint = new Paint();
    private final Paint activePaint = new Paint();

    public DotsIndicatorDecoration(int radius, int padding, int indicatorHeight, @ColorInt int colorInactive, @ColorInt int colorActive) {
        float strokeWidth = Resources.getSystem().getDisplayMetrics().density * 1;
        this.radius = radius;
        inactivePaint.setStrokeCap(Paint.Cap.ROUND);
        inactivePaint.setStrokeWidth(strokeWidth);
        inactivePaint.setStyle(Paint.Style.STROKE);
        inactivePaint.setAntiAlias(true);
        inactivePaint.setColor(colorInactive);

        activePaint.setStrokeCap(Paint.Cap.ROUND);
        activePaint.setStrokeWidth(strokeWidth);
        activePaint.setStyle(Paint.Style.FILL);
        activePaint.setAntiAlias(true);
        activePaint.setColor(colorActive);

        this.indicatorItemPadding = padding;
        this.indicatorHeight = indicatorHeight;
    }

    @Override
    public void onDrawOver(@NotNull Canvas c, @NotNull RecyclerView parent, @NotNull RecyclerView.State state) {
        super.onDrawOver(c, parent, state);

        final RecyclerView.Adapter adapter = parent.getAdapter();

        if (adapter == null) {
            return;
        }

        int itemCount = adapter.getItemCount();

        // center horizontally, calculate width and subtract half from center
        float totalLength = this.radius * 2 * itemCount;
        float paddingBetweenItems = Math.max(0, itemCount - 1) * indicatorItemPadding;
        float indicatorTotalWidth = totalLength + paddingBetweenItems;
        float indicatorStartX = (parent.getWidth() - indicatorTotalWidth) / 2f;

        // center vertically in the allotted space
        float indicatorPosY = parent.getHeight() - indicatorHeight / 2f;

        drawInactiveDots(c, indicatorStartX, indicatorPosY, itemCount);

        final int activePosition;

        if (parent.getLayoutManager() instanceof GridLayoutManager) {
            activePosition = ((GridLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition();
        } else if (parent.getLayoutManager() instanceof LinearLayoutManager) {
            activePosition = ((LinearLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition();
        } else {
            // not supported layout manager
            return;
        }

        if (activePosition == RecyclerView.NO_POSITION) {
            return;
        }

        // find offset of active page if the user is scrolling
        final View activeChild = parent.getLayoutManager().findViewByPosition(activePosition);
        if (activeChild == null) {
            return;
        }

        drawActiveDot(c, indicatorStartX, indicatorPosY, activePosition);
    }

    private void drawInactiveDots(Canvas c, float indicatorStartX, float indicatorPosY, int itemCount) {
        // width of item indicator including padding
        final float itemWidth = this.radius * 2 + indicatorItemPadding;

        float start = indicatorStartX + radius;
        for (int i = 0; i < itemCount; i++) {
            c.drawCircle(start, indicatorPosY, radius, inactivePaint);
            start += itemWidth;
        }
    }

    private void drawActiveDot(Canvas c, float indicatorStartX, float indicatorPosY,
                               int highlightPosition) {
        // width of item indicator including padding
        final float itemWidth = this.radius * 2 + indicatorItemPadding;
        float highlightStart = indicatorStartX + radius + itemWidth * highlightPosition;
        c.drawCircle(highlightStart, indicatorPosY, radius, activePaint);
    }

    @Override
    public void getItemOffsets(@NotNull Rect outRect, @NotNull View view, @NotNull RecyclerView parent, @NotNull RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        outRect.bottom = indicatorHeight;
    }
}

使用法:

        RecyclerView recyclerView = resourceLayout.getSuccessView().findViewById(R.id.cardsRecyclerView);
        recyclerView.setNestedScrollingEnabled(false);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
        recyclerView.setHasFixedSize(true);
        recyclerView.setAdapter(manageCardGenericAdapter);
        final int radius = getResources().getDimensionPixelSize(R.dimen.radius);
        final int dotsHeight = getResources().getDimensionPixelSize(R.dimen.dots_height);
        final int color = ContextCompat.getColor(getContext(), R.color.primaryBlue);
        recyclerView.addItemDecoration(new DotsIndicatorDecoration(radius, radius * 4, dotsHeight, color, color));
        new PagerSnapHelper().attachToRecyclerView(recyclerView);
6
Alexey

これをチェックしてください: https://blog.davidmedenjak.com/Android/2017/06/24/viewpager-recyclerview.html

Tldr: LinePagerIndicatorDecoration を作成し、RecyclerViewに追加します。

// pager indicator
recyclerView.addItemDecoration(new LinePagerIndicatorDecoration());
4

私はデコレータで決定を試みました-奇妙な動作:私の水平方向のリサイクラービューは画面の端にくっつきません。私の決定をチェックしてください-

        recycler.setAdapter(recyclerViewHorizontalAdapter);
        recycler.setOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            int currentCompletelyVisibleLab = ((LinearLayoutManager)recyclerViewLayoutManager).findFirstCompletelyVisibleItemPosition();
            bottomDotsTransaction(currentCompletelyVisibleLab);
        }
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        }
    });
    addBottomDots();
    setLabsOnTouchListener(commercialLabsNames, availableTests);
}
//create empty linear layout below recyclerview and add dots to it
private void addBottomDots() {
    ImageView imageView;
    for (int i = 0; i < commercialLabsLogos.size(); i++) {
        imageView = new ImageView(getContext());
        imageView.setImageResource(R.drawable.empty_dot_4dp);
        imageView.setPadding(15, 15, 15, 15);
        dotsLinearLayout.addView(imageView);
    }
    bottomDotsTransaction(0);
}
private void bottomDotsTransaction(int pos) {
    for (int i = 0; i < dotsLinearLayout.getChildCount(); i++) {
        if (dotsLinearLayout.getChildAt(i) instanceof ImageView) {
            ((ImageView) dotsLinearLayout.getChildAt(i)).setImageResource(R.drawable.empty_dot_4dp);
        }
    }
    //Set the chosen dot on position
    ((ImageView) dotsLinearLayout.getChildAt(pos)).setImageResource(R.drawable.fill_dot_6dp);
}

onScrollListenerを設定し、そのコールバック内で、layout_managerとメソッドを介してドットで線形レイアウトを再定義する必要があるだけです

    .findFirstCompletelyVisibleItemPosition()
or
    .findLastVisibleItemPosition()
    .findLastCompletelyVisibleItemPosition()
1
Kirguduck