都在骂钉钉的同时,我却仿照他的群列表开始学习

(代码过长,可以到http://blog.houxinlin.com/project/android/dingding.tar.gz进行下载)

一、效果图

在这里插入图片描述

二、实现过程

首先定义数据信息类,包括基本的姓名,头像,加入时间。家长和学生扩展自BaseInfo


在这里插入图片描述

学生信息定义如下,并扩展了一个家长集合。


在这里插入图片描述

家长信息定义如下,其中扩展了和学生的关系名称,并持有一份学生的信息。
在这里插入图片描述

MainActivity.java

这里的学生和家长信息使用Android提供的ArrayMap保存,key是单个字母,value是一堆StudentEntity集合,而StudentEntity中又包含一堆StudentFamily集合,存放多个家长信息。

首先是把所有学生的姓名拼音首字母提取出来,然后存放到ArrayMap中(ArrayMap可以通过下标进行访问元素)。最终形成单个字母对应多个学生,单个学生又对应多个家长信息的结构。

提取拼音可以使用com.belerweb:pinyin4这个框架。

  implementation 'com.belerweb:pinyin4j:2.5.0'
import android.os.Bundle;
import android.util.ArrayMap;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.hxl.gongzhonghaodemo.dingding.adapter.StudentAdapter;
import com.hxl.gongzhonghaodemo.dingding.entitys.StudentEntity;
import com.hxl.gongzhonghaodemo.dingding.entitys.StudentFamily;

import net.sourceforge.pinyin4j.PinyinHelper;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();

    private RecyclerView mRecyclerView;


    private StudentAdapter mStudentAdapter;

    private ArrayMap> mStudentMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();

        mStudentAdapter = new StudentAdapter(this, mStudentMap);

        mRecyclerView.setAdapter(mStudentAdapter);


    }

    private void initData() {
        mStudentMap = new ArrayMap<>();

        List mStudentEntities    = new ArrayList<>();

        mStudentEntities.add(new StudentEntity.Builder()
                .setName("鲁迅")
                .setUrl("http://img5.imgtn.bdimg.com/it/u=3841760432,773912449&fm=11&gp=0.jpg")
                .addFamily(new StudentFamily("鲁豫", "", LocalDateTime.now(), "陌生人"))
                .addFamily(new StudentFamily("鲁智深", "", LocalDateTime.now(), "陌生人"))
                .build());
        mStudentEntities.add(new StudentEntity.Builder()
                .setName("孔子")
                .setUrl("http://img2.imgtn.bdimg.com/it/u=3927250071,3411280749&fm=26&gp=0.jpg")
                .addFamily(new StudentFamily("孔融", "", LocalDateTime.now(), "儿子"))
                .addFamily(new StudentFamily("老子", "", LocalDateTime.now(), "陌生人"))
                .addFamily(new StudentFamily("孔明灯", "", LocalDateTime.now(), "天灯"))
                .build());

        mStudentEntities.add(new StudentEntity.Builder()
                .setName("李白")
                .setUrl("")
                .addFamily(new StudentFamily("李太白", "http://img0.imgtn.bdimg.com/it/u=3293099503,606929711&fm=26&gp=0.jpg", LocalDateTime.now(), "爸爸"))
                .addFamily(new StudentFamily("李太黑", "", LocalDateTime.now(), "妈妈"))
                .build());

        mStudentEntities.add(new StudentEntity.Builder()
                .setName("杜甫")
                .setUrl("http://img0.imgtn.bdimg.com/it/u=3593446461,3335288407&fm=26&gp=0.jpg")
                .addFamily(new StudentFamily("杜太甫", "http://img0.imgtn.bdimg.com/it/u=3293099503,606929711&fm=26&gp=0.jpg", LocalDateTime.now(), "爷爷"))
                .addFamily(new StudentFamily("杜绢花", "https://img.pconline.com.cn/images/upload/upc/tx/photoblog/1405/25/c1/34592098_34592098_1400979781687_mthumb.jpg", LocalDateTime.now(), "妈妈"))
                .build());

        mStudentEntities.add(new StudentEntity.Builder()
                .setName("白居易")
                .setUrl("http://img2.imgtn.bdimg.com/it/u=1473741299,1011020019&fm=26&gp=0.jpg")
                .addFamily(new StudentFamily("白行简", "http://img0.imgtn.bdimg.com/it/u=3293099503,606929711&fm=26&gp=0.jpg", LocalDateTime.now(), "姑姑"))
                .addFamily(new StudentFamily("白天鹅", "", LocalDateTime.now(), "宠物"))
                .addFamily(new StudentFamily("杜甫", "", LocalDateTime.now(), "兄弟"))

                .build());

        for (int i = 0; i < mStudentEntities.size(); i++) {
            StudentEntity item = mStudentEntities.get(i);
            char sort = getPinYinFirstLetter(item.getName().charAt(0));
            if (mStudentMap.get(sort) == null) {
                List data = new ArrayList<>();
                data.add(item);
                mStudentMap.put(sort, data);
            } else {
                List studentEntities = mStudentMap.get(sort);
                studentEntities.add(item);
            }
        }

    }

    private void initView() {
        mRecyclerView = findViewById(R.id.recycleview);

        mRecyclerView.setLayoutManager(new LinearLayoutManager(this, RecyclerView.VERTICAL, false));
    }

    public char getPinYinFirstLetter(char str) {
        String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(str);
        if (pinyinArray==null){
            return '#';
        }
        return pinyinArray==null?'#':Character.toUpperCase(pinyinArray[0].charAt(0));
    }

}

StudentAdapter.java
RecyclerView的适配器,这里自定义了几个ViewGroup,如StudentViewGroup用来存放学生信息的视图列表。

import android.content.Context;
import android.util.ArrayMap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

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

import com.hxl.gongzhonghaodemo.R;
import com.hxl.gongzhonghaodemo.dingding.entitys.StudentEntity;
import com.hxl.gongzhonghaodemo.dingding.ui.StudentViewGroup;

import java.util.List;

public class StudentAdapter extends RecyclerView.Adapter {
    private Context mContext;

    private ArrayMap> map;

    public StudentAdapter(Context context, ArrayMap> map) {
        this.mContext = context;
        this.map = map;
    }

    @NonNull
    @Override
    public RecycleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View inflate = LayoutInflater.from(mContext).inflate(R.layout.item_group, parent, false);
        return  new RecycleViewHolder(inflate);
    }

    @Override
    public void onBindViewHolder(@NonNull RecycleViewHolder holder, int position) {

        holder.mTvSort.setText(map.keyAt(position)+"");
        List studentEntities = map.get(map.keyAt(position));

        for (int i = 0; i 

以下是学生信息的视图和家长信息的视图。


import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.Nullable;

import com.hxl.gongzhonghaodemo.R;
import com.hxl.gongzhonghaodemo.dingding.entitys.BaseInfo;
import com.hxl.gongzhonghaodemo.dingding.entitys.StudentEntity;
import com.hxl.gongzhonghaodemo.dingding.entitys.StudentFamily;
import com.hxl.gongzhonghaodemo.dingding.utils.DisplayUtils;

public class BaseItemLayout extends LinearLayout {
    public BaseItemLayout(Context context) {
        super(context);
        init();
    }

    public BaseItemLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

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

    private void init() {
        setOrientation(LinearLayout.VERTICAL);
    }

    private View addItem(BaseInfo baseInfo, int resId) {
        if (baseInfo == null) {
            return null;
        }
        View mView = LayoutInflater.from(getContext()).inflate(resId, this, false);
        if (baseInfo instanceof StudentFamily){
            ((TextView) mView.findViewById(R.id.tv_name))
                    .setText(((StudentFamily) baseInfo).getStudentEntity().getName()+"的"+((StudentFamily) baseInfo).getRelation()+"("+baseInfo.getName()+")");
        }else {
            ((TextView) mView.findViewById(R.id.tv_name)).setText(baseInfo.getName());
        }
        ProfilePicture mProfilePicture = mView.findViewById(R.id.im_profile_picture);
        int size = DisplayUtils.dip2px(getContext(), 40);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(size, size);
        mProfilePicture.setLayoutParams(params);
        mProfilePicture.setName(baseInfo);
        this.addView(mView);
        return mView;
    }

    public View addItem(BaseInfo baseInfo) {
        if (this instanceof StudentViewGroup) {
           return addItem(baseInfo, R.layout.item_student);
        } else {
            return  addItem(baseInfo, R.layout.item_student_family);
        }

    }
}



public class StudentViewGroup  extends BaseItemLayout {
    private static  String TAG="StudentViewGroup";
    private  static  Paint mNamePaint;
    public StudentViewGroup(Context context) {
        super(context);
    }

    public StudentViewGroup(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public StudentViewGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    public  void addStudent(StudentEntity studentEntity){
        //添加自个
        View mView = addItem(studentEntity);

        //添加家人
        FamilyViewGroup mFamilyList = mView.findViewById(R.id.family_list);
        mFamilyList.addFamilyName(studentEntity.getStudentFamilies());
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
}


import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;

import androidx.annotation.Nullable;

import com.hxl.gongzhonghaodemo.dingding.entitys.StudentFamily;

import java.util.List;

public class FamilyViewGroup extends BaseItemLayout {
    public FamilyViewGroup(Context context) {
        super(context);
    }

    public FamilyViewGroup(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public FamilyViewGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    
    public  void addFamilyName(List studentFamilies) {
        for (int i = 0; i < studentFamilies.size(); i++) {
            addItem(studentFamilies.get(i));
        }
    }

}

其中自定义了个圆角视图RoundRelativeLayout和头像视图ProfilePicture。当没有头像url地址时,使用自己名字后两位,如果有,则使用Glide加载。

package com.hxl.gongzhonghaodemo.dingding.ui;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RelativeLayout;

public class RoundRelativeLayout extends RelativeLayout {
    private final RectF mRectF = new RectF();
    private final Paint maskPaint = new Paint();
    private final Paint zonePaint = new Paint();
    private View mView;
    private Context mContext;
    public RoundRelativeLayout(Context context) {
        super(context);
        init();
    }

    public RoundRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RoundRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    private void init() {

        maskPaint.setAntiAlias(true);
        maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        zonePaint.setColor(Color.WHITE);
    }
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        mRectF.set(0,0,getWidth(),getHeight());
    }
    @Override
    public void draw(Canvas canvas) {
        canvas.saveLayer(mRectF, zonePaint, Canvas.ALL_SAVE_FLAG);
        canvas.drawRoundRect(mRectF, getWidth(), getWidth(), zonePaint);
        canvas.saveLayer(mRectF, maskPaint, Canvas.ALL_SAVE_FLAG);
        super.draw(canvas);
        canvas.restore();
    }


}


import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.hxl.gongzhonghaodemo.dingding.entitys.BaseInfo;

public class ProfilePicture extends RoundRelativeLayout {

    public ProfilePicture(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ProfilePicture(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

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

    public void setName(BaseInfo baseInfo) {
        if (baseInfo.getProfilePicture() == null || baseInfo.getProfilePicture().length() == 0) {
            TextView mName = new TextView(getContext());
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.MATCH_PARENT);
            mName.setLayoutParams(params);
            String name = baseInfo.getName().length() > 2 ? 
                    baseInfo.getName().substring(baseInfo.getName().length() - 2) : baseInfo.getName();
            mName.setText(name);
            mName.setGravity(Gravity.CENTER);
            this.addView(mName);
            mName.setTextColor(Color.WHITE);
            return;
        }
        ImageView imageView =new ImageView(getContext());
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        Glide.with(imageView).load(baseInfo.getProfilePicture()).into(imageView);
        this.addView(imageView);
    }
}


你可能感兴趣的:(都在骂钉钉的同时,我却仿照他的群列表开始学习)