<android>视频流横向列表左滑加载更多,松手跳转页面,自定义view,RecyclerView,Horizontal,文字竖向居中排列

先上效果:


整体思路很简单,利用列表上拉加载更多的原理,图中“左划加载”的view作为Adapter最后一个itemView,我们将自定义这个itemView, 根据recyclerView的左滑距离来操作这个自定义view, 然后再封装一下BaseAdapter,让子Adapter继承并实现它的方法即可。也可以通过自定义属性moreViewHideMode=true隐藏这个view, 就会有从外侧拉进来的效果。不足之处后期会及时更新。

HorizontalMoreDataView:

public class HorizontalMoreDataView extends View {
    private Paint paint;
    private int mCenterY;
    private int mCenterX;
    int x = 0;
    private Paint fontPaint;
    int fontSize = 35;
    float fontHeight = 0;
    private float offset;
    String title = "左划加载";
    String jumpTitle = "松开跳转";
    String content = "";
    private int diverWidth;
    private int dampingNum = 80;
    private int changeNum = 5;
    private int mWidth;
    private int viewWidth = -1;
    private boolean hideMode;
    private char[] chars;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            try {
                ViewGroup.LayoutParams layoutParams = getLayoutParams();
                layoutParams.width = mWidth;
                setLayoutParams(layoutParams);
            } catch (Exception e) {
            }
        }
    };

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

    public HorizontalMoreDataView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }


    /**
     * 初始化
     *
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HorizontalMoreDataView, defStyleAttr, 0);
        fontSize = typedArray.getLayoutDimension(R.styleable.HorizontalMoreDataView_moreViewTextSize, -1);
        title = typedArray.getString(R.styleable.HorizontalMoreDataView_moreViewText);
        jumpTitle = typedArray.getString(R.styleable.HorizontalMoreDataView_moreViewJumpText);
        diverWidth = typedArray.getLayoutDimension(R.styleable.HorizontalMoreDataView_moreViewDiverWidth, 5);
        hideMode = typedArray.getBoolean(R.styleable.HorizontalMoreDataView_moreViewHideMode, false);
        content = title;
        fontHeight = fontSize / 1.94f;
        typedArray.recycle();

        paint = new Paint();
        paint.setStrokeWidth(diverWidth);
        paint.setColor(Color.parseColor("#333333"));
        paint.setStyle(Paint.Style.STROKE);
        paint.setAntiAlias(true);
        paint.setDither(true);

        fontPaint = new Paint();
        fontPaint.setStrokeWidth(7);
        fontPaint.setColor(Color.parseColor("#333333"));
        fontPaint.setTextSize(fontSize);
        fontPaint.setAntiAlias(true);
        fontPaint.setDither(true);
        offset = (fontPaint.getFontMetrics().top + fontPaint.getFontMetrics().bottom) / 2; //文字偏移量4
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (hideMode) {
            width = 0;
            hideMode = false;
        }
        if (viewWidth == -1)
            viewWidth = width;
        setMeasuredDimension(width, height);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mCenterY = getHeight() / 2;
        mCenterX = getWidth() / 2;

        Path path = new Path();
        path.moveTo(mCenterX / 1.6F, mCenterY - mCenterY / 3);
        path.lineTo(mCenterX / 1.6F - x, mCenterY);
        path.lineTo(mCenterX / 1.6F, mCenterY + mCenterY / 3);
        canvas.drawPath(path, paint);
        chars = content.toCharArray();

        //文字竖向居中排布处理
        for (int i = 0; i < chars.length; i++) {
            if (chars.length % 2 == 0) { //偶数索引
                if (i == (chars.length / 2 - 1)) //中间位置的 靠上第一个
                    canvas.drawText(chars[i] + "", mCenterX, mCenterY - (fontSize * 1.4F) / 2 - offset, fontPaint);

                if (i == (chars.length / 2)) //中间位置的 靠下第一个
                    canvas.drawText(chars[i] + "", mCenterX, mCenterY + (fontSize * 1.4F) / 2 - offset, fontPaint);

                if (i < (chars.length / 2 - 1)) { // 靠上第一个的 上边的n个
                    int num = Math.abs((chars.length / 2 - 1) - i); //间隔个数
                    canvas.drawText(chars[i] + "", mCenterX, mCenterY - (num * ((fontSize * 1.4F)) + ((fontSize * 1.4F)) / 2) - offset, fontPaint);
                }

                if (i > (chars.length / 2)) {  //靠下第一个的 下边的n个
                    int num = Math.abs(i - (chars.length / 2));
                    canvas.drawText(chars[i] + "", mCenterX, mCenterY + (num * ((fontSize * 1.4F)) + ((fontSize * 1.4F)) / 2) - offset, fontPaint);
                }

            } else { //奇数索引

                if (i == ((chars.length - 1) / 2)) //中间位置
                    canvas.drawText(chars[i] + "", mCenterX, mCenterY - offset, fontPaint);

                if (i < ((chars.length - 1) / 2)) { //中间以上的
                    int num = Math.abs(i - (chars.length / 2));
                    canvas.drawText(chars[i] + "", mCenterX, mCenterY - (num * ((fontSize * 1.4F))) - offset, fontPaint);
                }

                if (i > ((chars.length - 1) / 2)) { //中间以下的
                    int num = Math.abs(i - (chars.length / 2));
                    canvas.drawText(chars[i] + "", mCenterX, mCenterY + (num * ((fontSize * 1.4F))) - offset, fontPaint);
                }

            }

        }

    }


    /**
     * 设置移动距离
     *
     * @param distance
     */
    public void setSlipDistance(int distance) {
        x = distance / dampingNum;
        if (x > changeNum) {
            content = jumpTitle;
        } else {
            content = title;
        }
        invalidate();
        mWidth = viewWidth + ((distance - 50) / 5);
        ViewGroup.LayoutParams layoutParams = getLayoutParams();
        layoutParams.width = mWidth;
        setLayoutParams(layoutParams);
    }

    /**
     * 是否到达可跳转的阀值
     * @return
     */
    public boolean getCanJump() {
        return x > changeNum;
    }


    /**
     * 手指释放 恢复view
     */
    public void release() {
        x = 0;
        content = title;
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (mWidth >= viewWidth) {
                    try {
                        Thread.sleep(1);
                        mWidth = mWidth - 6;
                        handler.sendEmptyMessage(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        invalidate();
    }

}

HorizontalMoreBaseAdapter:

public abstract class HorizontalMoreBaseAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    public HorizontalMoreDataView horizontalView;
    public static int MOREDATAVIEWTYPE = 9000;
    private float x1;
    private float y1;
    private float x2;
    private float y2;

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (viewType == 9000) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.horizontal_more_view_footer, null);
            return new HorizontalMoreDataViewViewHolder(view);
        } else {
            return HorizontalMoreOnCreateViewHolder(parent, viewType);
        }
    }


    @Override
    public int getItemViewType(int position) {
        if (position == getItemCount() - 1) {
            return MOREDATAVIEWTYPE;
        } else {
            return HorizontalMoreGetItemViewType(position);
        }
    }


    class HorizontalMoreDataViewViewHolder extends RecyclerView.ViewHolder {
        public HorizontalMoreDataViewViewHolder(@NonNull View itemView) {
            super(itemView);
            horizontalView = (HorizontalMoreDataView) itemView.findViewById(R.id.horzonView);
        }
    }


    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        recyclerView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {//当手指按下的时候
                    x1 = event.getX();
                    y1 = event.getY();
                }
                if (event.getAction() == MotionEvent.ACTION_MOVE) {//当手指移动的时候
                    x2 = event.getX();
                    y2 = event.getY();
                    //45度分割 横向滑动
                    if (Math.abs(x2 - x1) > 50 && Math.abs(x2 - x1) > Math.abs(y2 - y1)) {
                        if (horizontalView != null)
                            horizontalView.setSlipDistance((int) (Math.abs(x1 - x2)));
                    }
                    //纵向滑动
                    if (Math.abs(y2 - y1) > 50 && Math.abs(y2 - y1) > Math.abs(x2 - x1)) {
                    }
                }
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    x1 = 0;
                    x2 = 0;
                    if (horizontalView != null) {
                        if (horizontalView.getCanJump() && relaseJumpActivityListener != null)
                            relaseJumpActivityListener.relaseJump();
                        horizontalView.release();
                    }

                }
                return false;
            }

        });
    }


    public abstract RecyclerView.ViewHolder HorizontalMoreOnCreateViewHolder(@NonNull ViewGroup parent, int viewType);
    public abstract int HorizontalMoreGetItemViewType(int postion);
    RelaseJumpActivityListener relaseJumpActivityListener;

    public void setRelaseJumpActivityListener(RelaseJumpActivityListener relaseJumpActivityListener) {
        this.relaseJumpActivityListener = relaseJumpActivityListener;
    }

    public interface RelaseJumpActivityListener {
        void relaseJump();
    }
}
horizontal_more_view_footer(xml):
<com.xxx.xx.utils.HorizontalMoreDataView
    android:background="#fff"
    app:moreViewTextSize="16sp"
    app:moreViewText="左划加载"
    app:moreViewJumpText="松开跳转"
    app:moreViewDiverWidth="5"
    app:moreViewHideMode="false"
    android:id="@+id/horzonView"
    android:layout_width="55dp"
    android:layout_height="wrap_content">

</com.watcn.wat.utils.HorizontalMoreDataView>

自定义属性:

<declare-styleable name="HorizontalMoreDataView">
    <attr name="moreViewTextSize" format="dimension"/>
    <attr name="moreViewText" format="string"/>
    <attr name="moreViewJumpText" format="string"/>
    <attr name="moreViewDiverWidth" format="integer"/>
    <attr name="moreViewHideMode" format="boolean"/>
</declare-styleable>
MainActivity(使用方法):
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(linearLayoutManager);
MyAdapter   myAdapter = new MyAdapter();
recyclerView.setAdapter(myAdapter);
myAdapter.setRelaseJumpActivityListener(new HorizontalMoreBaseAdapter.RelaseJumpActivityListener() {
    @Override
    public void relaseJump() {
        Toast.showToast("跳转新Activity");
    }
});

adapter继承HorizontalMoreBaseAdapter,实现HorizontalMoreOnCreateViewHolder和HorizontalMoreGetItemViewType,按照adapter的写法继续写就可以了。当然有很多的属性也应该提供出来,后期完善会及时更新。不足之处还请大佬们多多指教。

Android开发中,`LinearLayout` 是一个用于布局的视图组,它按照垂直或水平的方式排列其内部的子视图(`View`)。若要将两个`<View>`在`LinearLayout`中居中显示,可以使用`android:layout_gravity`属性来实现,具体步骤如下: 1. 将`LinearLayout`的`android:orientation`属性设置为`horizontal`或`vertical`,以确定是水平还是垂直排列子视图。 2. 对于每个需要居中的`<View>`,设置`android:layout_gravity`属性为`center`,这样这个视图就会在`LinearLayout`中居中显示。 示例代码如下: ```xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" <!-- 或者 "horizontal" --> android:gravity="center" <!-- 使LinearLayout内的内容垂直和水平居中 --> android:padding="16dp"> <View android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" <!-- 使这个View在LinearLayout中居中 --> android:background="#FF0000" /> <View android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" <!-- 同样使这个View居中 --> android:background="#00FF00" /> </LinearLayout> ``` 在上述代码中,两个`<View>`都使用了`android:layout_gravity="center"`属性,使得它们在垂直(`vertical`)方向的`LinearLayout`中居中显示。`android:gravity="center"`属性确保了`LinearLayout`内的所有内容(包括这两个`<View>`)在其父容器中水平和垂直居中
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值