At the same time, I started to learn by imitating his group list

Keywords: Android Java

(the code is too long, you can download it at http://blog.houxinlin.com/project/android/dinging.tar.gz)

1, Renderings

2, Implementation process

First of all, define the data information class, including the basic name, head portrait, and joining time. Parents and students expand from BaseInfo

Student information is defined as follows, and a parent set is expanded.

Parent information is defined as follows, which extends the name of the relationship with the student and holds a copy of the student's information.

MainActivity.java

The student and parent information here is saved using the ArrayMap provided by Android. The key is a single letter, the value is a collection of studententies, and studententies contain a collection of studentfamilies to store multiple parent information.

First, extract all students' initials and store them in ArrayMap (ArrayMap can access elements through subscripts). Finally, a single letter corresponds to multiple students, and a single student corresponds to multiple parent information structure.

The framework of com. Bellerweb: Pinyin4 can be used to extract Pinyin.

  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<Character, List<StudentEntity>> 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<StudentEntity> mStudentEntities    = new ArrayList<>();

        mStudentEntities.add(new StudentEntity.Builder()
                .setName("Lu Xun")
                .setUrl("http://img5.imgtn.bdimg.com/it/u=3841760432,773912449&fm=11&gp=0.jpg")
                .addFamily(new StudentFamily("Lu Yu", "", LocalDateTime.now(), "Stranger"))
                .addFamily(new StudentFamily("Lu Zhishen", "", LocalDateTime.now(), "Stranger"))
                .build());
        mStudentEntities.add(new StudentEntity.Builder()
                .setName("Confucius")
                .setUrl("http://img2.imgtn.bdimg.com/it/u=3927250071,3411280749&fm=26&gp=0.jpg")
                .addFamily(new StudentFamily("Kong Rong", "", LocalDateTime.now(), "Son"))
                .addFamily(new StudentFamily("Lao Tzu", "", LocalDateTime.now(), "Stranger"))
                .addFamily(new StudentFamily("Kongming latern", "", LocalDateTime.now(), "Sky lantern"))
                .build());

        mStudentEntities.add(new StudentEntity.Builder()
                .setName("Li Bai")
                .setUrl("")
                .addFamily(new StudentFamily("Li Tai Bai", "http://img0.imgtn.bdimg.com/it/u=3293099503,606929711&fm=26&gp=0.jpg", LocalDateTime.now(), "Dad"))
                .addFamily(new StudentFamily("Li Tai Hai", "", LocalDateTime.now(), "Mom"))
                .build());

        mStudentEntities.add(new StudentEntity.Builder()
                .setName("Du Fu")
                .setUrl("http://img0.imgtn.bdimg.com/it/u=3593446461,3335288407&fm=26&gp=0.jpg")
                .addFamily(new StudentFamily("Du Tai Fu", "http://img0.imgtn.bdimg.com/it/u=3293099503,606929711&fm=26&gp=0.jpg", LocalDateTime.now(), "grandpa"))
                .addFamily(new StudentFamily("Silk flower", "https://img.pconline.com.cn/images/upload/upc/tx/photoblog/1405/25/c1/34592098_34592098_1400979781687_mthumb.jpg", LocalDateTime.now(), "Mom"))
                .build());

        mStudentEntities.add(new StudentEntity.Builder()
                .setName("Bai Juyi")
                .setUrl("http://img2.imgtn.bdimg.com/it/u=1473741299,1011020019&fm=26&gp=0.jpg")
                .addFamily(new StudentFamily("White bamboo slip", "http://img0.imgtn.bdimg.com/it/u=3293099503,606929711&fm=26&gp=0.jpg", LocalDateTime.now(), "aunt"))
                .addFamily(new StudentFamily("White Swan", "", LocalDateTime.now(), "Pets"))
                .addFamily(new StudentFamily("Du Fu", "", LocalDateTime.now(), "Brother"))

                .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<StudentEntity> data = new ArrayList<>();
                data.add(item);
                mStudentMap.put(sort, data);
            } else {
                List<StudentEntity> 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 adapter. Here you have customized several view groups, such as the view list used by StudentViewGroup to store student information.

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<StudentAdapter.RecycleViewHolder> {
    private Context mContext;

    private ArrayMap<Character,List<StudentEntity>> map;

    public StudentAdapter(Context context, ArrayMap<Character, List<StudentEntity>> 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<StudentEntity> studentEntities = map.get(map.keyAt(position));

        for (int i = 0; i <studentEntities.size() ; i++) {
            holder.mStudentList.addStudent(studentEntities.get(i));
        }

    }

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

    public  class  RecycleViewHolder extends RecyclerView.ViewHolder{
        TextView mTvSort;
        StudentViewGroup mStudentList;

        public RecycleViewHolder(@NonNull View itemView) {
            super(itemView);
            mTvSort=itemView.findViewById(R.id.tv_sort);
            mStudentList =itemView.findViewById(R.id.student_list);
        }
    }
}

The following are views of student information and parent information.

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()+"Of"+((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){
        //Add self
        View mView = addItem(studentEntity);

        //Add family members
        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<StudentFamily> studentFamilies) {
        for (int i = 0; i < studentFamilies.size(); i++) {
            addItem(studentFamilies.get(i));
        }
    }

}

Among them, round relative layout and profile picture are customized. When there is no url address for the avatar, use the last two digits of your name. If there is one, use Glide to load it.

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);
    }
}


37 original articles published, 7 praised, 7163 visited
Private letter follow

Posted by davidlenehan on Thu, 27 Feb 2020 23:42:27 -0800