IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android第二次作业:RecyclerView的设计 -> 正文阅读

[移动开发]Android第二次作业:RecyclerView的设计

1.实验环境:

Windows系统,Android Studio

2.界面分析:

?

3.界面的代码实现:

3.1分隔线的实现

每个联系人与联系人之间有着一条分隔线分隔开来

核心代码如下:

/**
 * 设置屏幕的方向
 * @param orientation    LinearLayout布局是垂直还是水平
 */
public void setOrientation(int orientation){
    if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST){
        throw new IllegalArgumentException("invalid orientation");
    }
    mOrientation = orientation;
}

/**
 * 用于绘画分隔线
 * @param c   画布
 * @param parent   recyclerview组件
 * @param state
 */
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
    if (mOrientation == HORIZONTAL_LIST){
        drawVerticalLine(c, parent, state);
    }else {
        drawHorizontalLine(c, parent, state);
    }
}
/**
 * 画横线, 这里的parent其实是显示在屏幕显示的这部分
 * @param c   画布
 * @param parent     recyclerview组件
 * @param state
 */
public void drawHorizontalLine(Canvas c, RecyclerView parent, RecyclerView.State state){
    int left = parent.getPaddingLeft();
    int right = parent.getWidth() - parent.getPaddingRight();
    final int childCount = parent.getChildCount();
    for (int i = 0; i < childCount; i++){
        final View child = parent.getChildAt(i);

        //获得child的布局信息
        final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)child.getLayoutParams();
        final int top = child.getBottom() + params.bottomMargin;
        final int bottom = top + mDivider.getIntrinsicHeight();
        mDivider.setBounds(left, top, right, bottom);
        mDivider.draw(c);
        //Log.d("wnw", left + " " + top + " "+right+"   "+bottom+" "+i);
    }
}
/**
 * 由于Divider也有长宽高,每一个Item需要向下或者向右偏移
 * @param outRect   用于设置分隔线的坐标信息
 * @param view
 * @param parent   recyclerview组件
 * @param state
 */
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    if(mOrientation == HORIZONTAL_LIST){
        //画横线,就是往下偏移一个分割线的高度
        outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
    }else {
        //画竖线,就是往右偏移一个分割线的宽度
        outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
    }

    super.getItemOffsets(outRect, view, parent, state);
    if (users == null || users.size() == 0) {
        return;
    }

    int position = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewAdapterPosition();
    if (position > users.size() - 1 || position < 0) {
        return;
    }
    // 第一个分类不需要显示分类章节
    if (position > 0 && !TextUtils.equals(users.get(position).getFirstChar(), users.get(position - 1).getFirstChar())) {
        outRect.set(0, mDecorationHeight, 0, 0);
    }
}

3.2stickyHeader效果

页面最上面永远是当前用户的开头字母

实现代码如下:

?

public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);

    int left = parent.getPaddingLeft();
    int right = parent.getWidth() - parent.getPaddingRight();

    int childCount = parent.getChildCount();
    for (int i = 0; i < childCount; i++) {
        View child = parent.getChildAt(i);
        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
        int position = params.getViewAdapterPosition();
        if (position < 0 ){
            return;
        }
        String indexName = users.get(position).getFirstChar();
        if (indexName == null) {
            continue;
        }
        if (position > 0 && !TextUtils.equals(indexName, users.get(position - 1).getFirstChar())) {
            // 背景
            int top = child.getTop() - params.topMargin - mDecorationHeight;
            int bottom = top + mDecorationHeight;
            c.drawRect(left, top, right, bottom, mBgPaint);
            // 文字
            mTextPaint.getTextBounds(indexName, 0, indexName.length(), mTextBounds);
            int h = mTextBounds.height();
            c.drawText(indexName, left + textMarginLeft, bottom - (mDecorationHeight - h) / 2.0f, mTextPaint);
        }
    }
}
@Override
    public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        int firstVisibleItemPosition = ((LinearLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition();
        // 第一个也不展示decoration
//        if (firstVisibleItemPosition <= 0) {
//            return;
//        }

        boolean hasTrans = false;
        String indexName = users.get(firstVisibleItemPosition).getFirstChar();
        // 移动decoration
        if (firstVisibleItemPosition + 1 < users.size()) {
            String nextIndexName = users.get(firstVisibleItemPosition + 1).getFirstChar();
            if (!TextUtils.equals(indexName, nextIndexName)) {
                View firstVisibleChild = parent.getChildAt(0);
                int transY = firstVisibleChild.getBottom() - (parent.getPaddingTop() + mDecorationHeight);
                if (transY < 0) {
                    c.save();
                    c.translate(0, transY);
                    hasTrans = true;
                }
            }
        }
        float left = parent.getLeft();
        float top = parent.getPaddingTop();
        float right = parent.getWidth() - parent.getPaddingRight();
        float bottom = top + mDecorationHeight;
        // 背景
        c.drawRect(left, top, right, bottom, mBgPaint);
        mTextPaint.getTextBounds(indexName, 0, indexName.length(), mTextBounds);
        //文字
        float baseline = bottom - (mDecorationHeight - mTextBounds.height()) / 2.0f;
        c.drawText(indexName, parent.getPaddingLeft() + textMarginLeft, baseline, mTextPaint);
        if (hasTrans) {
            c.restore();
        }
    }
}

3.3头像功能的实现

将方形的图片转换为圆形的头像

实现代码如下:

public class CircleImageView extends androidx.appcompat.widget.AppCompatImageView {
@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //由于是圆形,宽高应保持一致
        int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
        mRadius = size / 2;
        setMeasuredDimension(size, size);
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {

        mPaint = new Paint();

        Drawable drawable = getDrawable();

        if (null != drawable) {
            Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();

            //初始化BitmapShader,传入bitmap对象
            BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            //计算缩放比例
            mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());

            Matrix matrix = new Matrix();
            matrix.setScale(mScale, mScale);
            bitmapShader.setLocalMatrix(matrix);
            mPaint.setShader(bitmapShader);
            //画圆形,指定好坐标,半径,画笔
            canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
        } else {
            super.onDraw(canvas);
        }
    }
}

然后在我们设置的xml文件中添加我们创建的CircleImageView

<com.example.homework.CircleImageView
    android:id="@+id/imageView"
    android:layout_width="104dp"
    android:layout_height="102dp"
    app:srcCompat="@drawable/img1"
    android:layout_marginTop="5dp"
    android:layout_marginBottom="5dp"/>

3.4点击事件的绑定

提示当前是什么用户

实现代码:

class MyVIewHolder extends RecyclerView.ViewHolder{
    TextView textView1;
    ImageView image;
    //初始化控件
    public MyVIewHolder(@NonNull View itemView) {
        super(itemView);
        textView1 = itemView.findViewById(R.id.textView2);
        image = itemView.findViewById(R.id.imageView);
        textView1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context,"当前点击查看的用户为:"+textView1.getText(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

3.5联系人的换位以及删除

用于交换不同联系人的位置以及删除某些联系人

实现代码如下:

public class Callback extends ItemTouchHelper.Callback{
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView,
                            @NonNull RecyclerView.ViewHolder viewHolder) {
    // 设置拖动方向, 此处设置上下拖动事件
    int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
    // 设置滑动方向, 此处设置左右侧滑事件
    int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
    // 应用 拖动 和 滑动 设置
    return makeMovementFlags(dragFlags, swipeFlags);
}
**
 * 是否启用长按拖动功能
 * @return
 */
@Override
public boolean isLongPressDragEnabled() {
    return true;
}
/**
 * 拖动幅度设置
 * 组件在宽度 / 高度 上移动超过该比例 , 就认为拖动触发, 执行拖动相关操作
 * @param viewHolder
 * @return
 */
@Override
public float getMoveThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {
    // 该案例中, 拖动操作只能上下进行
    // 拖动超过条目组件高度超过 0.8 倍, 即可触发拖动操作
    return 0.8f;
}
//调用设置的move移动方法
@Override
public void onMoved(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, int fromPos, @NonNull RecyclerView.ViewHolder target, int toPos, int x, int y) {
  mAdapter.moveItem(viewHolder.getAdapterPosition(),target.getAdapterPosition());
}
/**
 * 是否启用滑动操作
 * @return 是否启用 true 启用, false 不启用
 */
@Override
public boolean isItemViewSwipeEnabled() {
    return true;
}
/**
 * 用户滑动距离, 设置的是比例值, 返回值为 0.5 , 就意味着滑动宽度/高度的一半, 才触发侧滑 onSwiped 方法
 * @param viewHolder
 * @return
 */
@Override
public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {
    return 0.5f;
}
/**
 * 滑动判定速度, 每秒移动的像素个数, 达到该速度后, 才可以被判定为滑动
 * @param defaultValue
 * @return
 */
@Override
public float getSwipeEscapeVelocity(float defaultValue) {
    return 5000f;
}
/**
 * 滑动时的回调操作
 * @param viewHolder
 * @param direction
 */
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
    Log.i(TAG, "触发侧滑删除条目");
    // 滑动指定的距离, 达到一定幅度后, 就会触发该方法回调
    // 这里做的是滑动删除功能, 直接删除滑动项
    // 该方法中删除指定条目, 并刷新界面
    mAdapter.deleteItem(viewHolder.getAdapterPosition());
}

4.小结

本次实验通过创建继承于ItemDecoration类的MyDecoration类并且重写其中的一些方法来实现了分隔线以及StickHeader的效果,通过创建继承于ImageView类的CircleViewImage类并重写其中的方法实现了圆形头像的作用,最后通过重写CallBack类中的某些方法来实现了最后的删除以及换位的功能。通过本次实验,更加清晰的了解了RecyclerView与Adapter的作用,以及其中的方法的实现。而且通过本次对recyclerView效果的实现,熟悉了ItemDecoration类以及Callback类的某些方法,对TextView,ImageView以及LinearLayout的使用更加的娴熟。

https://gitee.com/tao-jie/MyHomework

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-18 17:30:27  更:2021-10-18 17:30:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:54:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码