自定义温度控制控件

自定义温度控制控件

百度的自定义控件

请添加图片描述

package com.learn.navigationdemo;

import static com.learn.navigationdemo.Util.dpToPx;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class MPickerView extends View {
    private static final String TAG = MPickerView.class.getSimpleName();

    public static final float SPEED = 5;
    /**
     * 行距与mTextSizeNormal之比,保证View内显示的内容在适当的位置
     */
    private final float RATE = 2.7f;

    private final Paint mPaintNormal;
    private final Paint mPaintSelect;
    private final Paint mPaintText;
    private final Paint mPaintLine;

    private float mTextSizeNormal;
    private float mTextSizeSelect;

    private final float mTextAlphaSelect;
    private final float mTextAlphaNormal;

    private float mPaddingStart;
    private float mPaddingEnd;

    /**
     * 选中的位置
     */
    private int mSelectPosition;
    /**
     * 开始触摸的位置
     */
    private float mStartTouchY;
    /**
     * 手指滑动的距离
     */
    private float mMoveDistance;
    private int mWidth;
    private int mHeight;
    private String mText;

    private final Timer mTimer;
    private MTimerTask mTask;
    private final Handler mHandler;
    private final Context mContext;
    private final List<String> mData;
    private final Resources mResources;
    private OnSelectListener mOnSelectListener;

    public MPickerView(Context context) {
        this(context, null);
    }

    public MPickerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MPickerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        mResources = mContext.getResources();
        mPaintNormal = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintSelect = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintText = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintLine = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintNormal.setTextAlign(Paint.Align.CENTER);
        mPaintSelect.setTextAlign(Paint.Align.CENTER);
        mPaintNormal.setTextSize(mTextSizeNormal);
        mPaintSelect.setTextSize(mTextSizeSelect);
        mPaintText.setTextSize(dpToPx(context, 15));
        mPaintSelect.setColor(0xffa000);
        mPaintNormal.setColor(0xa2a2a2);
        mPaintText.setColor(mResources.getColor(R.color.colorPickViewDefaultSelect));
        mPaintLine.setColor(mContext.getResources().getColor(R.color.colorDivider));
        mPaintLine.setStrokeWidth(dpToPx(context, 0.5f));
        mHandler = new MHandler(this);
        mData = new ArrayList<>();
        mTimer = new Timer();
        mTextAlphaSelect = 255;
        mTextAlphaNormal = 120;
    }

    public void setOnSelectListener(OnSelectListener onSelectListener) {
        this.mOnSelectListener = onSelectListener;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        mTextSizeSelect = mResources.getDisplayMetrics().density * 70 / 3;
        mTextSizeNormal = mTextSizeSelect / 2f;

        // 默认宽高
        mPaintSelect.setTextSize(mTextSizeSelect);
        mPaintNormal.setTextSize(mTextSizeNormal);
        int mDefaultWidth = (int) (mPaintSelect.measureText("0000") + mPaintText.measureText("℃") * 2);
        Paint.FontMetricsInt mAnIntSelect = mPaintSelect.getFontMetricsInt();
        Paint.FontMetricsInt mAnIntNormal = mPaintNormal.getFontMetricsInt();
        int mDefaultHeight = mAnIntSelect.bottom - mAnIntSelect.top + (mAnIntNormal.bottom - mAnIntNormal.top) * 4;

        if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT &&
            getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
            setMeasuredDimension(mDefaultWidth, mDefaultHeight);
        } else if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT) {
            setMeasuredDimension(mDefaultWidth, heightSize);
        } else if (getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
            setMeasuredDimension(widthSize, mDefaultHeight);
        }

        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaddingStart = getPaddingStart();
        mPaddingEnd = getPaddingEnd();
        // 绘制中间位置
        draw(canvas, 1, 0, mPaintSelect);
        // 绘制上方数据
        for (int i = 1; i < mSelectPosition - 2; i++) {
            draw(canvas, -1, i, mPaintNormal);
        }
        // 绘制下方数据
        for (int i = 1; (mSelectPosition + i) < mData.size() - 2; i++) {
            draw(canvas, 1, i, mPaintNormal);
        }
        invalidate();
    }

    private void draw(Canvas canvas, int type, int position, Paint paint) {
        float space = RATE * mTextSizeNormal * position + type * mMoveDistance;
        float scale = parabola(mHeight / 4.0f, space);
        float size = (mTextSizeSelect - mTextSizeNormal) * scale + mTextSizeNormal;
        int alpha = (int) ((mTextAlphaSelect - mTextAlphaNormal) * scale + mTextAlphaNormal);
        paint.setTextSize(size);
        paint.setAlpha(alpha);

        float x = mWidth / 2.0f;
        float y = mHeight / 2.0f + type * space;
        Paint.FontMetricsInt fmi = paint.getFontMetricsInt();
        float baseline = y + (fmi.bottom - fmi.top) / 2.0f - fmi.descent - 2;
        float width = mPaintText.measureText("℃");
        if (position == 0) {
            canvas.drawText(mData.get(mSelectPosition) + "℃", x - width / 2 + mPaddingStart - mPaddingEnd, baseline, paint);
        } else {
            canvas.drawText(mData.get(mSelectPosition + type * position), x - width / 2 + mPaddingStart - mPaddingEnd, baseline, paint);
        }
    }

    private float parabola(float zero, float x) {
        float y = (float) (1 - Math.pow(x / zero, 2));
        return y < 0 ? 0 : y;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mStartTouchY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                mMoveDistance += (event.getY() - mStartTouchY);
                if (mMoveDistance > RATE * mTextSizeNormal / 2) {
                    // 向下滑动
                    moveTailToHead();
                    mMoveDistance = mMoveDistance - RATE * mTextSizeNormal;
                } else if (mMoveDistance < -RATE * mTextSizeNormal / 2) {
                    // 向上滑动
                    moveHeadToTail();
                    mMoveDistance = mMoveDistance + RATE * mTextSizeNormal;
                }
                mStartTouchY = event.getY();
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                if (Math.abs(mMoveDistance) < 0.0001) {
                    mMoveDistance = 0;
                    return true;
                }
                if (mTask != null) {
                    mTask.cancel();
                    mTask = null;
                }
                mTask = new MTimerTask(mHandler);
                mTimer.schedule(mTask, 0, 10);
        }
        return true;
    }

    public void setData(@NonNull List<String> data) {
        if (mData != null) {
            mData.clear();
            mData.addAll(data);
            mSelectPosition = data.size() / 2;
        }
    }

    public void increaseData() {
        setSelectPosition(mSelectPosition + 1);
    }

    public void decreaseData() {
        setSelectPosition(mSelectPosition - 1);
    }

    public void setText(String mText) {
        this.mText = mText;
    }

    private void moveHeadToTail() {
        if (mData.size() > 0) {
            String head = mData.get(0);
            mData.remove(0);
            mData.add(head);
        }
    }

    private void moveTailToHead() {
        if (mData.size() > 0) {
            String tail = mData.get(mData.size() - 1);
            mData.remove(mData.size() - 1);
            mData.add(0, tail);
        }
    }

    private void setSelectPosition(int position) {
        mSelectPosition = position;
        int value = mData.size() / 2 - mSelectPosition;
        if (value < 0) {
            for (int i = 0; i < -value; i++) {
                moveHeadToTail();
                mSelectPosition--;
            }
        } else if (value > 0) {
            for (int i = 0; i < value; i++) {
                moveTailToHead();
                mSelectPosition++;
            }
        }
        invalidate();
    }

    public void setDefaultValue(@NonNull String value) {
        if (mData.size() > 0) {
            for (int i = 0; i < mData.size(); i++) {
                if (value.equals(mData.get(i))) {
                    setSelectPosition(i);
                    break;
                }
            }
        }
    }

    public String getSelectValue() {
        return mData.size() > 0 ? mData.get(mSelectPosition) : "";
    }

    static class MHandler extends Handler {
        private final WeakReference<View> mWeakReference;

        MHandler(View view) {
            this.mWeakReference = new WeakReference<>(view);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            MPickerView mPickerView = (MPickerView) mWeakReference.get();
            if (mPickerView != null) {
                if (Math.abs(mPickerView.mMoveDistance) < SPEED) {
                    mPickerView.mMoveDistance = 0;
                    if (mPickerView.mTask != null) {
                        mPickerView.mTask.cancel();
                        mPickerView.mTask = null;
                        if (mPickerView.mOnSelectListener != null)
                            mPickerView.mOnSelectListener.onSelect(mPickerView, mPickerView.mData.get(mPickerView.mSelectPosition));
                    }
                } else {
                    mPickerView.mMoveDistance = mPickerView.mMoveDistance - mPickerView.mMoveDistance /
                        Math.abs(mPickerView.mMoveDistance) * SPEED;
                }
                mPickerView.invalidate();
            }
        }
    }

    static class MTimerTask extends TimerTask {
        final Handler handler;

        MTimerTask(Handler handler) {
            this.handler = handler;
        }

        @Override
        public void run() {
            handler.sendMessage(handler.obtainMessage());
        }
    }

    public interface OnSelectListener {
        void onSelect(View view, String data);
    }

}

效果跟预期不符,所以放弃了。想着使用ViewPager2应该也可以实现,如下:

ViewPager2实现

请添加图片描述

布局文件
androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/view_pager_layout"
    android:layout_width="wrap_content"
    android:layout_height="240px"
    android:background="@color/purple_200"
    android:clipChildren="false"
    app:layout_constraintBottom_toTopOf="@+id/decrease"
    app:layout_constraintEnd_toEndOf="parent">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/rightViewPager"
        android:layout_width="200px"
        android:layout_height="100px"
        android:background="@color/teal_200"
        android:clipChildren="false"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
item布局文件
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/temp"
            android:layout_width="match_parent"
            android:layout_height="100px"
            android:gravity="center"
            android:text="111"
            android:textSize="32px"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

注意:布局必须为match_parent

Adapter
package com.learn.navigationdemo.temp;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;

import com.learn.navigationdemo.R;
import com.learn.navigationdemo.databinding.ItemBinding;

import java.util.ArrayList;
import java.util.List;

public class TempAdapter extends RecyclerView.Adapter<TempAdapter.MyViewModel> {
    private static final String TAG = "TempAdapter";
    private List<String> mList = new ArrayList<>();
    private ItemBinding mItemBinding;

    public void setList(List<String> list) {
        if (mList != null) {
            mList.clear();
            mList.addAll(list);
        }
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public MyViewModel onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        mItemBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),
            R.layout.item, parent, false);
        return new MyViewModel(mItemBinding);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewModel holder, int position) {
        if (holder instanceof MyViewModel) {
            holder.binding(position);
        }
    }

    @Override
    public int getItemCount() {
        return mList == null ? 0 : mList.size();
    }

    public class MyViewModel extends RecyclerView.ViewHolder {

        ItemBinding mBinding;

        public MyViewModel(@NonNull ItemBinding itemBinding) {
            super(itemBinding.getRoot());
            mBinding = itemBinding;
        }

        public void binding(int position) {
                if (position == 0) {
                    mBinding.temp.setText("LO");
                } else if (position == mList.size() - 1) {
                    mBinding.temp.setText("HI");
                } else {
                    mBinding.temp.setText(mList.get(position) + "℃");
                }
        }
    }
}
修改滑动速度
package com.learn.navigationdemo.temp;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.util.Log;
import android.view.animation.AccelerateDecelerateInterpolator;

import androidx.viewpager2.widget.ViewPager2;

/**
 * 设置ViewPage2的切换时间
 */
public class MyPagerHelper {
    private static final String TAG = "MyPagerHelper";
    /**
     * 保存前一个animatedValue.
     */
    private static int previousValue;

    /**
     * 切换Item.
     *
     * @param pager    viewpager2
     * @param item     下一个跳转的item
     * @param duration scroll时长
     */
    public static void setCurrentItem(final ViewPager2 pager, int item, long duration) {
        previousValue = 0;
        int currentItem = pager.getCurrentItem();
        int pagerHeight = pager.getHeight();
        int pxToDrag = pagerHeight * (item - currentItem);
        Log.d(TAG, "setCurrentItem: pxToDrag = " + pxToDrag);
        final ValueAnimator animator = ValueAnimator.ofInt(0, pxToDrag);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int currentValue = (int) animation.getAnimatedValue();
                float currentPxToDrag = (float) (currentValue - previousValue);
                pager.fakeDragBy(-currentPxToDrag);
                previousValue = currentValue;
            }
        });
        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                pager.beginFakeDrag();
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                pager.endFakeDrag();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        });
        animator.setInterpolator(new AccelerateDecelerateInterpolator());
        animator.setDuration(duration);
        animator.start();
    }
}
设置Transform
package com.learn.navigationdemo.temp;

import android.view.View;

import androidx.annotation.NonNull;
import androidx.viewpager2.widget.ViewPager2;

public class TempTransformer implements ViewPager2.PageTransformer {
    //自由控制缩放比例
    private static final float MAX_SCALE = 1f;
    private static final float MIN_SCALE = 0.6f;

    @Override
    public void transformPage(@NonNull View page, float position) {
        if (position <= 1) {
            float scaleFactor = MIN_SCALE + (1 - Math.abs(position)) * (MAX_SCALE - MIN_SCALE);
            page.setScaleX(scaleFactor);
            page.setScaleY(scaleFactor);
        } else {
            page.setScaleX(MIN_SCALE);
            page.setScaleY(MIN_SCALE);
        }
    }
}
使用
		mBinding.rightViewPager.setAdapter(mTempAdapter);
        mBinding.rightViewPager.setOffscreenPageLimit(3);
        mBinding.rightViewPager.setPageTransformer(new TempTransformer());
        mBinding.rightViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                Log.d(TAG, "onPageSelected: position = " + position);
            }
        });
        mTempAdapter.setList(mList);

其实这样实现的效果已经满足需求,但是项目上要求的是左右两个相同的同时可以调节,使用的时候发现有些小问题,改了半天放弃了,决定使用ViewPager实现一下:

ViewPager

请添加图片描述

布局文件
            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="wrap_content"
                android:layout_height="300px"
                android:clipChildren="false"
                app:layout_constraintBottom_toTopOf="@+id/mp_view"
                app:layout_constraintEnd_toEndOf="@+id/mp_view"
                app:layout_constraintStart_toStartOf="@+id/mp_view">

                <androidx.viewpager.widget.ViewPager
                    android:id="@+id/view_pager"
                    android:layout_width="100px"
                    android:layout_height="300px"
                    android:background="@color/teal_200"
                    android:clipChildren="false"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />
            </androidx.constraintlayout.widget.ConstraintLayout>
item布局
 <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/temp"
            android:layout_width="match_parent"
            android:layout_height="100px"
            android:gravity="center"
            android:text="111"
            android:textSize="32px"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
Adapter
package com.learn.navigationdemo;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.viewpager.widget.PagerAdapter;

import com.learn.navigationdemo.databinding.ItemBinding;

import java.util.ArrayList;
import java.util.List;

public class MyAdapter extends PagerAdapter {
    private static final String TAG = "MyAdapter";

    private List<String> mList = new ArrayList<>();
    private ItemBinding mBinding;

    public void setList(List<String> list) {
        if (mList != null) {
            mList.clear();
            mList.addAll(list);
        }
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return mList.size();
    }

    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        return view == object;
    }

    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        //加载vp的布局
        mBinding = DataBindingUtil.inflate(LayoutInflater.from(container.getContext()), R.layout.item, container, false);
        mBinding.getRoot().setTag(position);
        //给布局控件赋值
        if (position == 0) {
            mBinding.temp.setText("LO");
        } else if (position == mList.size() - 1) {
            mBinding.temp.setText("HI");
        } else {
            mBinding.temp.setText(mList.get(position) + "℃");
        }
        mBinding.getRoot().setRotation(90);
        //添加一个布局(不添加无效果)
        container.addView(mBinding.getRoot());
        return mBinding.getRoot();
    }

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        //移除视图
        container.removeView((View) object);
    }
}

设置Transform
package com.learn.navigationdemo;

import android.view.View;

import androidx.annotation.NonNull;
import androidx.viewpager.widget.ViewPager;

public class ViewPagerTransformer implements ViewPager.PageTransformer {

    //自由控制缩放比例
    private static final float MAX_SCALE = 1f;
    private static final float MIN_SCALE = 0.6f;

    @Override
    public void transformPage(@NonNull View page, float position) {
        if (position < 1) {
            float scaleFactor = MIN_SCALE + (1 - Math.abs(position)) * (MAX_SCALE - MIN_SCALE);
            page.setScaleX(scaleFactor);
            page.setScaleY(scaleFactor);
        } else {
            page.setScaleX(MIN_SCALE);
            page.setScaleY(MIN_SCALE);
        }
    }
}
自定义Scroller
package com.learn.navigationdemo;

import android.content.Context;
import android.view.animation.Interpolator;
import android.widget.Scroller;

public class FixedSpeedScroller extends Scroller {
    private int mCurrentDuration = 200;

    public FixedSpeedScroller(Context context) {
        super(context);
    }

    public FixedSpeedScroller(Context context, Interpolator interpolator) {
        super(context, interpolator);
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
        // Ignore received duration, use fixed one instead
        super.startScroll(startX, startY, dx, dy, mCurrentDuration);
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy) {
        // Ignore received duration, use fixed one instead
        super.startScroll(startX, startY, dx, dy, mCurrentDuration);
    }

    public void setCurrentDuration(int time) {
        mCurrentDuration = time;
    }

    public int getCurrentDuration() {
        return mCurrentDuration;
    }
}
使用
MyAdapter myAdapter = new MyAdapter();
        myAdapter.setList(mList);
        mBinding.viewPager.setAdapter(myAdapter);
        mBinding.viewPager.setOffscreenPageLimit(3);
		//设置View Pager垂直
        mBinding.viewPager.setRotation(-90);
        mBinding.viewPager.setPageTransformer(false, new ViewPagerTransformer());
        mBinding.viewPager.setCurrentItem(mList.size() / 2);
		//修改滑动速度
        try {
            Field field = ViewPager.class.getDeclaredField("mScroller");
            field.setAccessible(true);
            FixedSpeedScroller scroller = new FixedSpeedScroller(mBinding.viewPager.getContext(),
                new AccelerateInterpolator());
            field.set(mBinding.viewPager, scroller);
            scroller.setCurrentDuration(200);
        } catch (Exception e) {

        }
        mBinding.viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                Log.d(TAG, "onPageSelected: position = " + position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

这里要说明为什么ViewPager是垂直的,原因在于对ViewPager进行了viewPager.setRotation(-90);以及子视图的

mBinding.getRoot().setRotation(90);,这样就使得ViewPager是垂直的啦!!!但是这样实现的效果发现滑动的过程中会出现,上下两个item也会变大的问题还有就是刷新的问题,很烦,推倒重来使用Recycler View实现

RecyclerView

请添加图片描述

布局文件
<androidx.recyclerview.widget.RecyclerView
                android:id="@+id/leftRec"
                android:layout_width="200px"
                android:layout_height="300px"
                android:background="@color/teal_200"
                app:layout_constraintBottom_toTopOf="@+id/increase"
                app:layout_constraintStart_toStartOf="parent" />
item布局
<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="100px">

        <TextView
            android:id="@+id/temp_item"
            android:layout_width="match_parent"
            android:layout_height="100px"
            android:gravity="center"
            android:text="111"
            android:textSize="32px"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
解决首部和尾部不能居中的问题
package com.learn.navigationdemo.temp;

import android.graphics.Rect;
import android.view.View;

import androidx.recyclerview.widget.RecyclerView;

public class GalleryItemDecoration extends RecyclerView.ItemDecoration {
    public static final int MARGIN_VIEW_HEIGHT = 100;

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        //获取当前Item的position
        int position = parent.getChildAdapterPosition(view);
        //获得Item的数量
        int itemCount = parent.getAdapter().getItemCount();
        int topMargin;
        if (position == 0) {
            topMargin = MARGIN_VIEW_HEIGHT;
        } else {
            topMargin = 0;
        }
        int bottomMargin;
        if (position == itemCount - 1) {
            bottomMargin = MARGIN_VIEW_HEIGHT;
        } else {
            bottomMargin = 0;
        }
        RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
        layoutParams.setMargins(0, topMargin, 0, bottomMargin);
        view.setLayoutParams(layoutParams);
        super.getItemOffsets(outRect, view, parent, state);
    }

}

Adapter
package com.learn.navigationdemo;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;

import com.learn.navigationdemo.databinding.ItemBinding;
import com.learn.navigationdemo.databinding.RecItemBinding;

import java.util.ArrayList;
import java.util.List;

public class RecAdapter extends RecyclerView.Adapter<RecAdapter.MyViewModel> {
    private static final String TAG = "TempAdapter";
    private List<String> mList = new ArrayList<>();
    private RecItemBinding mItemBinding;

    public void setList(List<String> list) {
        if (mList != null) {
            mList.clear();
            mList.addAll(list);
        }
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public MyViewModel onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        mItemBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),
            R.layout.rec_item, parent, false);
        return new MyViewModel(mItemBinding);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewModel holder, int position, @NonNull List<Object> payloads) {
        super.onBindViewHolder(holder, position, payloads);
        Log.d(TAG, "onBindViewHolder: payloads = " + payloads);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewModel holder, int position) {
        if (holder instanceof MyViewModel) {
            holder.binding(position);
        }
    }

    @Override
    public int getItemCount() {
        return mList == null ? 0 : mList.size();
    }

    public class MyViewModel extends RecyclerView.ViewHolder {

        RecItemBinding mBinding;

        public MyViewModel(@NonNull RecItemBinding itemBinding) {
            super(itemBinding.getRoot());
            mBinding = itemBinding;
        }

        public void binding(int position) {
            if (position == 0) {
                mBinding.tempItem.setText("LO");
            } else if (position == mList.size() - 1) {
                mBinding.tempItem.setText("HI");
            } else {
                mBinding.tempItem.setText(mList.get(position) + "℃");
            }
        }
    }
}

使用
		recAdapter.setList(mList);
		//使得recyclerView的item可以以每个为单位滑动
        PagerSnapHelper pagerSnapHelper = new PagerSnapHelper();
        pagerSnapHelper.attachToRecyclerView(mBinding.leftRec);
		//使得首部和尾部居中
        mBinding.leftRec.addItemDecoration(new GalleryItemDecoration());
        mBinding.leftRec.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false));
        mBinding.leftRec.setAdapter(recAdapter);
        mBinding.leftRec.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    //暂停
                    if (layoutManager instanceof LinearLayoutManager) {
                        int firstCompletelyVisibleItemPosition = ((LinearLayoutManager) layoutManager).findFirstCompletelyVisibleItemPosition();
                        Log.d(TAG, "onViewCreated: firstCompletelyVisibleItemPosition = " + firstCompletelyVisibleItemPosition);
                    }
                }
            }

            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                //设置item进行缩放
                int childCount = recyclerView.getChildCount();
                int height = recyclerView.getHeight();
                for (int i = 0; i < childCount; i++) {
                    View child = recyclerView.getChildAt(i);
                    int top = child.getTop();
                    int bottom = child.getBottom();
                    // 遍历recyclerView子项,以中间项中心偏移量为基准进行缩放
                    float scale = (bottom - top) * 1.0f / 2 + top - height * 1.0f / 2;
                    float scaleFactor = MIN_SCALE + (1 - Math.min(1, Math.abs(scale / child.getHeight()))) * (MAX_SCALE - MIN_SCALE);
                    child.setScaleX(scaleFactor);
                    child.setScaleY(scaleFactor);
                }
            }
        });

其实这样写需求已经满足了,但是由于需要两个同时调节,这样写代码重复度太高了,可以考虑简单封装一下,但是局限性很高,这里就不贴了,至此才算真正完成了,爽了!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

立花泷える宫水三叶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值