Take you to a campus APP: campus address book module

Keywords: github Android Database xml

Campus address book function, collect and display the public contact information in the campus. It is often used in daily life. For example, when the water and electricity department has a problem, it needs to find a water and electricity master, an enrollment and employment office, a study and work office, etc.

Of course, for privacy reasons, personal cell phone numbers will not be collected and displayed. Only show office contact information and other numbers that can be found on the Internet or on campus.

Preface

The campus address book module aims to build a convenient campus information service platform, improve the campus information service, and provide a more convenient and safe service system for the management and maintenance of campus information.
(this paper is a simple implementation of this module, only about the display of address list style)

Serial articles

Github address: Science Division has campus APP

  1. Take you to a campus APP (I): Project Introduction
  2. Take you to a campus APP (2): application launch and welcome page
  3. Take you to a campus APP (3): user module (login, registration, etc.)
  4. A campus APP (4): APP framework and function design
  5. Take you to a campus APP (5): news page center module
  6. Take you to a c amp us APP (6): lost and found & second hand transaction module
  7. Hand in hand with you to roll up a campus APP (7): campus culture module (community activities & expression wall & illustration of campus)
  8. Take you to a campus APP (8): campus address book module
  9. Hand in hand with you to roll up a campus APP (9): curriculum module (simulated landing to access the curriculum information of the Academic Affairs Office)
  10. Take you to roll up a campus APP (10): APP general module (update, feedback, etc.)

Realization effect

Campus address book:

Analysis

  1. The data part of campus address book is relatively simple, including three main fields: name, department and contact information;
  2. The data in the address list needs to be sorted and grouped before being displayed;

Sort:
Sort by initials
==>Need to get Pinyin of initial character
==>Through tripartite Library TinyPinyin To achieve
Grouping:
It can be realized by customizing the ItemDecoration of RecycleView, and the display of the suspended window needs to be handled additionally

  1. The letter quick index list is displayed on the right side, associated with RecycleView, and can be associated with sliding

Implemented through custom controls

Realization

Note: the realization of this module mainly refers to the project of imitating Meizu address book of pony sprint, and on the basis of it, it optimizes the project, which pays tribute to the original author.

Github: Fake Meizu address book
Author: Pony run
Article: https://www.jianshu.com/p/7b7b7ee80c44

Database design

Field name describe type Is the primary key?
objectId Unique identification String yes
name Name and address String -
department department String -
tel Contact information String -

Android implementation

Here are the main ideas of the realization of the campus address book module:

step 1: data sorting

After relying on TinyPinyin library, process the source data and add the content of setting indexTag field. Then sort according to the field;

public static void sortData(List<Teacher> list) {
    if (list == null || list.size() == 0) return;
    for (int i = 0; i < list.size(); i++) {
        Teacher bean = list.get(i);
        String tag = Pinyin.toPinyin(bean.getName().substring(0, 1).charAt(0)).substring(0, 1);
        if (tag.matches("[A-Z]")) {
            bean.setIndexTag(tag);
        } else {
            bean.setIndexTag("#");
        }
    }
    Collections.sort(list, new Comparator<Teacher>() {
        @Override
        public int compare(Teacher o1, Teacher o2) {
            if ("#".equals(o1.getIndexTag())) {
                return 1;
            } else if ("#".equals(o2.getIndexTag())) {
                return -1;
            } else {
                return o1.getIndexTag().compareTo(o2.getIndexTag());
            }
        }
    });

step 2: data grouping

After sorting the data, draw the category tags on the hover box and ItemView by customizing ItemDecoration

//Margin used to draw each ItemView
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    //Some codes are omitted
    int position = parent.getChildAdapterPosition(view);
    if (position == 0) {
        //The first data has bar
        outRect.set(0, dividerHeight, 0, 0);
    } else if (position > 0) {
        if (TextUtils.isEmpty(mBeans.get(position).getIndexTag())) return;
        //Different from the tag in the previous data, bar is displayed
        if (!mBeans.get(position).getIndexTag().equals(mBeans.get(position - 1).getIndexTag())) {
            outRect.set(0, dividerHeight, 0, 0);
        }
    }
}

//Used to draw the top suspension box
@Override
 public void onDrawOver(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
     int position = ((LinearLayoutManager) (parent.getLayoutManager())).findFirstVisibleItemPosition();
     final int bottom = parent.getPaddingTop() + dividerHeight;
     mPaint.setColor(Color.WHITE);
     //Draw the extent of the hover box
     canvas.drawRect(parent.getLeft(), parent.getPaddingTop(), parent.getRight() - parent.getPaddingRight(), parent.getPaddingTop() + dividerHeight, mPaint);
     //Some codes are omitted
     mPaint.setTextSize(40);
     canvas.drawCircle(DpUtil.dp2px(mContext, 42.5f), bottom - dividerHeight / 2, 35, mPaint);
     mPaint.setColor(Color.WHITE);
     canvas.drawText(mBeans.get(position).getIndexTag(), DpUtil.dp2px(mContext, 42.5f), bottom - dividerHeight / 3, mPaint);
    }

//Draw category tags on ItemView as needed
@Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
    //Some codes are omitted
    final int childCount = parent.getChildCount();
    for (int i = 0; i < childCount; i++) {
        final View child = parent.getChildAt(i);
        final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
        int position = params.getViewLayoutPosition();
        if (position == 0) {
            //The first data has bar
            drawTitleBar(canvas, parent, child, mBeans.get(position), tagsStr.indexOf(mBeans.get(position).getIndexTag()));
        } else if (position > 0) {
            //Different from the tag in the previous data, bar is displayed
            if (!mBeans.get(position).getIndexTag().equals(mBeans.get(position - 1).getIndexTag())) {
                drawTitleBar(canvas, parent, child, mBeans.get(position), tagsStr.indexOf(mBeans.get(position).getIndexTag()));
            } } 
     }  
   }

step 3: customize the right index View

  • Draw the right navigation bar letter:
@Override
 protected void onDraw(Canvas canvas) {
    //for loop to draw all navigation bar letters
     for (int i = 0; i < indexStr.length(); i++) {
         String textTag = indexStr.substring(i, i + 1);
         float xPos = (mWidth - mPaint.measureText(textTag)) / 2;
         canvas.drawText(textTag, xPos, singleHeight * (i + 1) + DpUtil.dp2px(mContext, TOP_MARGIN), mPaint);
     }
 }
  • Handle sliding events:

In onTouchEvent, the sliding event is processed. When the fingers are sliding up and down, a circle on the left side will follow the sliding. Here, the user-defined IndexBar (IndexBar extensions ViewGroup, IndexBar contains SideBar) is used to process. When the SideBar sliding is in the MOVE state, a series of position parameters are transmitted to the IndexBar through ((IndexBar) getParent()).setDrawData()

 @Override
 public boolean onTouchEvent(MotionEvent event) {
    //Handle push slide events
     switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
             //Press down
             mPaint.setColor(Color.BLACK);
             invalidate();
        case MotionEvent.ACTION_MOVE:
             //Slide event.getY() to get the Y coordinate in the parent View, and then multiply the proportion to the total height by the total number of characters to get the position to be pressed
             int position = (int) ((event.getY() - getTop() - DpUtil.dp2px(mContext, 80)) / mHeight * indexStr.toCharArray().length);
             if (position >= 0 && position < indexStr.length()) {
                 ((IndexBar) getParent()).setDrawData(event.getY(), String.valueOf(indexStr.toCharArray()[position]), position);
                 if (listener != null) {
                     listener.indexChanged(indexStr.substring(position, position + 1));
                 }
             }
             break;
         case MotionEvent.ACTION_UP:
             //lift
             ((IndexBar) getParent()).setTagStatus(false);
             mPaint.setColor(Color.GRAY);
             invalidate();
             break;
     }
     return true;
 }

It mainly arranges SideBar to the far right in onLayout, and constantly changes the position of circle according to a series of position parameters transmitted from SideBar in onDraw,

Note here that the onDraw() method of the custom ViewGroup will not be called by default. If you want to execute the onDraw method, you can use the following two methods:
1. Set transparent background:
In the constructor: setBackgroundColor(Color.TRANSPARENT);
Or in xml: android:background="@color/transparent"
2. Or you can add setWillNotDraw(false) to the constructor;

@Override
 protected void onLayout(boolean changed, int l, int t, int r, int b) {
     int childNum = getChildCount();
     if (childNum <= 0) return;
     //Get SideBar
     View childView = getChildAt(0);
     childWidth = childView.getMeasuredWidth();
     //Arrange SideBar to the far right
     childView.layout((mWidth - childWidth), 0, mWidth, mHeight);
    }

@Override
 protected void onDraw(Canvas canvas) {
     super.onDraw(canvas);
     if (isShowTag) {
         //Constantly changing Paint color according to position
         ColorUtil.setPaintColor(mPaint, position);
         //Draw circles and text
         canvas.drawCircle((mWidth - childWidth) / 2, centerY, circleRadius, mPaint);
         mPaint.setColor(Color.WHITE);
         mPaint.setTextSize(80);
         canvas.drawText(tag, (mWidth - childWidth - mPaint.measureText(tag)) / 2, centerY - (mPaint.ascent() + mPaint.descent()) / 2, mPaint);
     }
 }

step 4: Associate RecycleView

sideBar.setIndexChangeListener(new SideBar.indexChangeListener() {
    @Override
    public void indexChanged(String tag) {
        if (TextUtils.isEmpty(tag) || contactList.size() <= 0) return;
        for (int i = 0; i < contactList.size(); i++) {
            if (tag.equals(contactList.get(i).getIndexTag())) {
                layoutManager.scrollToPositionWithOffset(i, 0);
                return;
            }
        }
    }
});

So far, the campus address book module is basically completed.
In the example of this paper, we use multiple tripartite libraries TextDrawableTinyPinyinFake Meizu address book Wait, once again, I salute you guys!

If this article is helpful to you, I hope you can enjoy a little praise~

Published 73 original articles, won praise 203, and visited 320000+
Private letter follow

Posted by surreal5335 on Wed, 19 Feb 2020 16:56:23 -0800