RecyclerView中的圆形寻呼机指示器没有固定位置

时间:2019-11-18 17:13:53

标签: android android-recyclerview

我正在使用此类作为水平RecyclerView(#2)中的物品装饰,它也包含在垂直RecyclerView(#1)中:

holder.recyclerView.addItemDecoration(new CirclePagerIndicatorDecoration());

CirclePagerIndicatorDecoration.java:

public class CirclePagerIndicatorDecoration extends RecyclerView.ItemDecoration {
    private int colorActive = 0xDEE54242;
    private int colorInactive = 0x33000000;

    private static final float DP = Resources.getSystem().getDisplayMetrics().density;
    private final int mIndicatorHeight = (int) (DP * 16);
    private final float mIndicatorStrokeWidth = DP * 4;
    private final float mIndicatorItemLength = DP * 4;
    private final float mIndicatorItemPadding = DP * 8;
    private final Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
    private final Paint mPaint = new Paint();

    public CirclePagerIndicatorDecoration() {
        mPaint.setStrokeWidth(mIndicatorStrokeWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setAntiAlias(true);
    }

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

        int itemCount = parent.getAdapter().getItemCount();

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

        // center vertically in the allotted space
        float indicatorPosY = parent.getHeight() - mIndicatorHeight * 2F;

        drawInactiveIndicators(c, indicatorStartX, indicatorPosY, itemCount);

        // find active page (which should be highlighted)
        LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
        int activePosition = layoutManager.findFirstVisibleItemPosition();
        if (activePosition == RecyclerView.NO_POSITION) {
            return;
        }

        // find offset of active page (if the user is scrolling)
        final View activeChild = layoutManager.findViewByPosition(activePosition);
        int left = activeChild.getLeft();
        int width = activeChild.getWidth();
        int right = activeChild.getRight();

        // on swipe the active item will be positioned from [-width, 0]
        // interpolate offset for smooth animation
        float progress = mInterpolator.getInterpolation(left * -1 / (float) width);

        drawHighlights(c, indicatorStartX, indicatorPosY, activePosition, progress);
    }

    private void drawInactiveIndicators(Canvas c, float indicatorStartX, float indicatorPosY, int itemCount) {
        mPaint.setColor(colorInactive);

        // width of item indicator including padding
        final float itemWidth = mIndicatorItemLength + mIndicatorItemPadding;

        float start = indicatorStartX;
        for (int i = 0; i < itemCount; i++) {

            c.drawCircle(start, indicatorPosY, mIndicatorItemLength / 2F, mPaint);
            start += itemWidth;
        }
    }

    private void drawHighlights(Canvas c, float indicatorStartX, float indicatorPosY,
                                int highlightPosition, float progress) {
        mPaint.setColor(colorActive);

        // width of item indicator including padding
        final float itemWidth = mIndicatorItemLength + mIndicatorItemPadding;

        if (progress == 0F) {
            // no swipe, draw a normal indicator
            float highlightStart = indicatorStartX + itemWidth * highlightPosition;

            c.drawCircle(highlightStart, indicatorPosY, mIndicatorItemLength / 2F, mPaint);

        } else {
            float highlightStart = indicatorStartX + itemWidth * highlightPosition;
            // calculate partial highlight
            float partialLength = mIndicatorItemLength * progress + mIndicatorItemPadding*progress;

            c.drawCircle(highlightStart + partialLength, indicatorPosY, mIndicatorItemLength / 2F, mPaint);
        }
    }

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

此代码有问题。

向下滚动recyclerView#1时,来自recyclerView#2的圆圈指示器并不总是显示在recyclerview#2的同一位置。

示例:来自recyclerView#1的项目1和来自recyclerView#2的项目1的圆形寻呼机指示器。

enter image description here

示例:来自recyclerView#1的项目5和来自recyclerView#2的项目1的圆形寻呼机指示器。

enter image description here

第二个问题是如何将位置从圆圈指示器更改到recyclerView#2的顶部。

编辑:RecyclerView#1布局:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cardview1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="10dp"
    android:background="@color/colorWhite"
    android:padding="10dp"
    card_view:cardCornerRadius="6dp"
    card_view:cardElevation="16dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <de.hdodenhof.circleimageview.CircleImageView
            android:id="@+id/profile_image"
            android:layout_width="65dp"
            android:layout_height="65dp"

            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:src="@drawable/ic_account_circle_black_24dp"
            card_view:civ_border_color="#FF000000"
            card_view:civ_border_width="2dp" />

        <TextView
            android:id="@+id/txtUsername"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="3dp"

            android:layout_marginBottom="3dp"
            android:layout_toRightOf="@id/profile_image"
            android:text="Sample"
            android:textColor="@color/grey_700"
            android:textSize="20dp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/txtDate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/txtUsername"
            android:layout_alignStart="@id/txtUsername"
            android:layout_toRightOf="@id/profile_image"
            android:text="TextView"
            android:textSize="10sp" />

        <LinearLayout
            android:id="@+id/layout_deportes"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignTop="@id/txtUsername"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="3dp"
            android:layout_toRightOf="@id/txtUsername"
            android:orientation="horizontal">

            <ImageView
                android:id="@+id/sp1"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginRight="5dp"
                android:layout_weight="1"
                android:visibility="visible"
                card_view:srcCompat="@drawable/skate" />

            <ImageView
                android:id="@+id/sp6"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_below="@+id/layout_deportes"
                android:layout_marginRight="5dp"
                android:layout_weight="1"
                android:visibility="visible"
                card_view:srcCompat="@drawable/skate" />

            <ImageView
                android:id="@+id/sp2"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginRight="5dp"
                android:layout_weight="1"
                android:visibility="visible"
                card_view:srcCompat="@drawable/skate" />

            <ImageView
                android:id="@+id/sp3"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginRight="5dp"
                android:layout_weight="1"
                android:visibility="visible"
                card_view:srcCompat="@drawable/skate" />

            <ImageView
                android:id="@+id/sp4"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginRight="5dp"
                android:layout_weight="1"
                android:visibility="visible"
                card_view:srcCompat="@drawable/skate" />

            <ImageView
                android:id="@+id/sp5"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginRight="5dp"
                android:layout_weight="1"
                android:visibility="visible"
                card_view:srcCompat="@drawable/skate" />

            <ImageView
                android:id="@+id/sp7"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginRight="5dp"
                android:layout_weight="1"
                android:visibility="visible"
                card_view:srcCompat="@drawable/skate" />

            <ImageView
                android:id="@+id/sp8"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginRight="5dp"
                android:layout_weight="1"
                android:visibility="visible"
                card_view:srcCompat="@drawable/skate" />

        </LinearLayout>

        <TextView
            android:id="@+id/txtDescription"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/profile_image"
            android:layout_marginStart="10dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginBottom="10dp"
            android:minLines="3"
            android:paddingRight="40dp"
            android:text="Vivimos rodeados de objetos cotidianos que, a pesar de verlos cada día, todavía no tenemos muy claro para qué sirven. Es el caso del cuadrado con dos ranuras que tienen algunas mochilas, el bolsillo pequeño de los vaqueros, sus remaches de cobre e incluso las siglas 'YKK' que aparecen en tu cremallera. ¿Alguna vez te habías preguntado para qué sirven los agujeros laterales de algunas zapatillas?    "
            android:textAlignment="textStart"
            android:textSize="14sp"
            android:textStyle="bold" />

        <ImageView
            android:id="@+id/addUser"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_below="@id/layout_deportes"
            android:layout_alignParentRight="true"
            android:layout_marginTop="5dp"
            android:layout_marginRight="5dp"
            card_view:srcCompat="@drawable/home_add_user" />

        <ImageView
            android:id="@+id/tres"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_below="@id/addUser"
            android:layout_alignParentRight="true"
            android:layout_marginTop="10dp"
            android:layout_marginRight="5dp"
            android:layout_marginBottom="5dp"
            card_view:srcCompat="@drawable/home_submenu" />

        <ImageView
            android:id="@+id/ivAmbassador"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_alignRight="@id/profile_image"
            android:layout_alignBottom="@id/profile_image"
            android:layout_marginLeft="50dp"
            card_view:srcCompat="@drawable/home_ambassador" />

        <ImageView
            android:id="@+id/spot_sport"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_below="@id/txtDescription"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="10dp"
            card_view:srcCompat="@drawable/skate" />

        <ImageView
            android:id="@+id/tipo_spot"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_below="@id/txtDescription"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="10dp"
            android:layout_toEndOf="@id/spot_sport"
            android:fadeScrollbars="true"
            card_view:srcCompat="@drawable/negocio" />

        <ImageView
            android:id="@+id/spot_map"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_below="@id/txtDescription"
            android:layout_alignBottom="@id/tipo_spot"
            android:layout_marginLeft="9dp"
            android:layout_marginTop="10dp"
            android:layout_toRightOf="@id/tipo_spot"
            android:fadeScrollbars="true"
            android:foregroundGravity="bottom"
            card_view:srcCompat="@drawable/home_pin_mapa" />

        <TextView
            android:id="@+id/spot"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/txtDescription"
            android:layout_marginTop="15dp"
            android:layout_toLeftOf="@id/verified"
            android:layout_toRightOf="@id/spot_map"
            android:ellipsize="end"
            android:maxLines="1"
            android:minLines="1"
            android:text="Skatepark Macba, Barcelona, Spain"
            android:textSize="12sp" />

        <ImageView
            android:id="@+id/verified"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_alignBottom="@id/spot_map"
            android:layout_marginLeft="24dp"
            android:layout_marginEnd="5dp"
            android:layout_toLeftOf="@id/txtVerified"
            card_view:srcCompat="@drawable/home_ambassador" />


        <TextView
            android:id="@+id/txtVerified"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/verified"
            android:layout_alignParentEnd="true"
            android:layout_marginLeft="25dp"
            android:layout_marginTop="-18dp"
            android:layout_marginEnd="25dp"
            android:text="Verified"
            android:textAlignment="textEnd"
            android:textSize="12sp" />

        <com.daimajia.slider.library.SliderLayout
            android:id="@+id/slider"
            android:layout_width="match_parent"
            android:layout_height="280dp"
            android:layout_below="@id/spot_sport"
            android:layout_marginTop="5dp"
            android:layout_marginBottom="5dp"
            android:visibility="gone" >

        </com.daimajia.slider.library.SliderLayout>

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerMarcas"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            android:layout_below="@id/spot_sport" />

        <ImageView
            android:id="@+id/fire"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_below="@id/recyclerMarcas"
            android:layout_marginStart="5dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:layout_marginEnd="5dp"
            android:layout_marginBottom="5dp"
            card_view:srcCompat="@drawable/home_fire_activado" />

        <ImageView
            android:id="@+id/comments"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_below="@id/recyclerMarcas"
            android:layout_marginStart="5dp"
            android:layout_marginTop="5dp"
            android:layout_marginEnd="5dp"
            android:layout_marginBottom="5dp"
            android:layout_toRightOf="@id/fire"
            card_view:srcCompat="@drawable/home_comentarios" />

        <ImageView
            android:id="@+id/fixpin"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_below="@id/recyclerMarcas"
            android:layout_marginStart="5dp"
            android:layout_marginTop="5dp"
            android:layout_marginEnd="5dp"
            android:layout_marginBottom="5dp"
            android:layout_toRightOf="@id/comments"
            card_view:srcCompat="@drawable/home_check" />

        <TextView
            android:id="@+id/txtEstadoAqui"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/recyclerMarcas"
            android:layout_alignBottom="@id/fixpin"
            android:layout_marginLeft="10dp"
            android:layout_toRightOf="@id/fixpin"

            android:gravity="center_horizontal|center_vertical"
            android:lines="2"
            android:text="He estado aqui"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/txtComments"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/recyclerMarcas"
            android:layout_alignBottom="@id/fixpin"
            android:layout_marginLeft="10dp"
            android:layout_toLeftOf="@id/fireresult"

            android:layout_toRightOf="@id/txtEstadoAqui"
            android:gravity="center_horizontal|center_vertical"
            android:lines="2"
            android:text="10 comments"
            android:textAlignment="viewEnd"
            android:textSize="14sp" />

        <ImageView
            android:id="@+id/fireresult"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_below="@id/recyclerMarcas"
            android:layout_alignParentEnd="true"
            android:layout_marginStart="5dp"
            android:layout_marginTop="-10dp"
            android:layout_marginEnd="5dp"
            android:layout_marginBottom="10dp"
            card_view:srcCompat="@drawable/home_fire_activado" />

    </RelativeLayout>


</androidx.cardview.widget.CardView>

1 个答案:

答案 0 :(得分:0)

我已经解决了仅将圆圈指示器放在recyclerView顶部的问题。

float indicatorPosY = 40;

现在它的位置在任何物品上都不会改变。