RecyclerView 列表控件中简单实现时间线

ʱ¼ä

ʱ¼ä£¬Ê±¼ä£¬Ê±¼ä°¡£»×ßÂýÒ»µã°É¡«

¿´¼ûºÜ¶àÈí¼þÖж¼ÓÐʱ¼äÏߵĶ«Î÷£¬Ã²ËÆÌìÆø°¡£¬ÂÃÓΰ¡Ê²Ã´µÄ×î¶àÁË£»¾ßÌåʵÏÖ·½Ê½ºÜ¶à£¬ÔÚ±¾ÆªÎÄÕÂÖн²½âÒ»ÖÖ×Ô¶¨ÒåView·â×°µÄ·½Ê½¡£

Ч¹û

ÏÈÀ´¿´¿´Ð§¹û¡£ 

blob.png

·ÖÎö

Èí¼þÖУ¬¿ÉÒÔ¿´¼ûÇ°ÃæµÄʱ¼äÏßÒ²¾ÍÊÇÏßÌõ¼ÓÉÏԲȦ×é³É£»µ±È»ÕâÀïµÄԲȦÓëÏßÌõÒ²¶¼ÊÇ¿ÉÒÔËæÒâ»»³ÉÆäËûµÄ£¬±ÈÈçͼƬµÈµÈ¡£

µ±È»ÕâÀï×î¼òµ¥µÄÀ´Ëµ£¬ÊÇÉÏÃæÒ»¸öÏßÌõ£¬È»ºóÒ»¸öԲȦ£¬È»ºóÏÂÃæÒ»¸öÏßÌõ£»ÉÏÏßÌõÔÚµÚÒ»ÌõÊý¾Ýʱ²»×öÏÔʾ£¬ÏÂÏßÌõÔÚ×îºóÒ»ÌõÊý¾Ýʱ²»×öÏÔʾ¡£

blob.png

ÕâÀï×Ô¶¨Òå²¼¾Ö²¿·ÖÒ²¾ÍÊÇ°ÑÅԱߵÄÏßÌõÓëԲȦ·â×°µ½Ò»Æ𣬲¢Ê¹Óüòµ¥µÄ·½·¨À´¿ØÖÆÊÇ·ñÏÔʾ¡£ 
µ±·â×°ºÃÁ˺ó£¬ÓëÅԱߵÄÎÄ×Ö²¿·ÖÒ²¾ÍÊÇˮƿ·½ÏòµÄÏßÐÔ²¼¾ÖÁË£¬È»ºóÉèÖÃΪÿһ¸öµÄRecyclerView µÄItemµÄ²¼¾ÖÒ²¾ÍÍê³ÉÁË¡£

¿Ø¼þ

¿Ø¼þºÜ¼òµ¥£¬Ê×ÏÈÎÒÃǼ̳ÐView£¬È¡ÃûΪ TimeLineMarker ¾ÍOK¡£

Attrs ÊôÐÔ

¿ªÊ¼¿Ø¼þ֮ǰÏÈ×¼±¸ºÃÐèÒªµÄÊôÐÔ¡£

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="TimeLineMarker">
        <attr name="markerSize" format="dimension" />
        <attr name="marker" format="color|reference" />
        <attr name="beginLine" format="color|reference" />
        <attr name="endLine" format="color|reference" />
        <attr name="lineSize" format="dimension" />
    </declare-styleable>
</resources>

ÔÚÕâÀïÒ²¾Í×¼±¸ÁËÏßÌõµÄ´óС¡¢¿ªÊ¼ÏßÌõ¡¢½áÊøÏßÌõ¡¢Öмä±êʾ²¿·Ö¼°´óС¡£

ÊôÐÔÓëÏÖʵ

    private int mMarkerSize = 24;
    private int mLineSize = 12;
    private Drawable mBeginLine;
    private Drawable mEndLine;
    private Drawable mMarkerDrawable;
    @Override
    protected void onDraw(Canvas canvas) {
        if (mBeginLine != null) {
            mBeginLine.draw(canvas);
        }
        if (mEndLine != null) {
            mEndLine.draw(canvas);
        }
        if (mMarkerDrawable != null) {
            mMarkerDrawable.draw(canvas);
        }
        super.onDraw(canvas);
    }

Á½¸ö´óСÊôÐÔ£¬3¸ö¾ßÌåµÄDrawable£¬È»ºóÔÚonDraw·½·¨ÖнøÐоßÌåµÄÏÔʾҲ¾ÍOK¡£

¹¹ÔìÓëÊôÐÔ³õʼ»¯

ÔÚÉÏÃæÎÒÃǶ¨ÒåÁËÊôÐÔ£¬ÔÚÕâÀïÎÒÃÇÔÚ¹¹Ô캯ÊýÖлñÈ¡XMLËùÉèÖõÄÊôÐÔ¡£

    public TimeLineMarker(Context context) {
        this(context, null);
    }
    public TimeLineMarker(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public TimeLineMarker(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs);
    }
    private void init(AttributeSet attrs) {
        // Load attributes
        final TypedArray a = getContext().obtainStyledAttributes(
                attrs, R.styleable.TimeLineMarker, 0, 0);
        mMarkerSize = a.getDimensionPixelSize(
                R.styleable.TimeLineMarker_markerSize,
                mMarkerSize);
        mLineSize = a.getDimensionPixelSize(
                R.styleable.TimeLineMarker_lineSize,
                mLineSize);
        mBeginLine = a.getDrawable(
                R.styleable.TimeLineMarker_beginLine);
        mEndLine = a.getDrawable(
                R.styleable.TimeLineMarker_endLine);
        mMarkerDrawable = a.getDrawable(
                R.styleable.TimeLineMarker_marker);
        a.recycle();
        if (mBeginLine != null)
            mBeginLine.setCallback(this);
        if (mEndLine != null)
            mEndLine.setCallback(this);
        if (mMarkerDrawable != null)
            mMarkerDrawable.setCallback(this);
    }

Drawable µÄλÖÃÓë´óС³õʼ»¯

ÊôÐÔɶµÄÓÐÁË£¬¾ßÌåµÄDrawable Ò²ÓÐÁË£¬ÒªÏÔʾµÄµØ·½µ÷ÓÃÒ²ÊÇOKÁË£»µ«ÊÇÈç¹ûûÓнøÐнøÐоßÌåµÄλÖõ÷ÕûÕâÒ»ÇÐÒ²¶¼Ã»ÓÐÒâÒå¡£

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        initDrawableSize();
    }
    private void initDrawableSize() {
        int pLeft = getPaddingLeft();
        int pRight = getPaddingRight();
        int pTop = getPaddingTop();
        int pBottom = getPaddingBottom();
        int width = getWidth();
        int height = getHeight();
        int cWidth = width - pLeft - pRight;
        int cHeight = height - pTop - pBottom;
        Rect bounds;
        if (mMarkerDrawable != null) {
            // Size
            int markerSize = Math.min(mMarkerSize, Math.min(cWidth, cHeight));
            mMarkerDrawable.setBounds(pLeft, pTop,
                    pLeft + markerSize, pTop + markerSize);
            bounds = mMarkerDrawable.getBounds();
        } else {
            bounds = new Rect(pLeft, pTop, pLeft + cWidth, pTop + cHeight);
        }
        int halfLineSize = mLineSize >> 1;
        int lineLeft = bounds.centerX() - halfLineSize;
        if (mBeginLine != null) {
            mBeginLine.setBounds(lineLeft, 0, lineLeft + mLineSize, bounds.top);
        }
        if (mEndLine != null) {
            mEndLine.setBounds(lineLeft, bounds.bottom, lineLeft + mLineSize, height);
        }
    }

initDrawableSize ·½·¨½øÐоßÌåµÄÔËË㣬¶øÔËËãµÄʱ¼äµã¾ÍÊǵ±¿Ø¼þµÄ´óС¸Ä±ä£¨onSizeChanged£©µÄʱºò¡£

ÔÚ³õʼ»¯ÖвÉÓÃÁËÒ»¶¨µÄͶ»úÈ¡ÇÉ£»ÕâÀïÀûÓÃÁËÉÏÄڱ߾àÓëÏÂÄڱ߾à·Ö±ð×÷ΪÉÏÏßÌõÓëÏÂÏßÌõµÄ³¤¶È£»¶øÏßÌõÓëÖмäµÄ±êʶ¶¼²ÉÓÃÁËˮƽ¾àÖС£

ÆäËûÉèÖ÷½·¨

    public void setLineSize(int lineSize) {
        if (mLineSize != lineSize) {
            this.mLineSize = lineSize;
            initDrawableSize();
            invalidate();
        }
    }
    public void setMarkerSize(int markerSize) {
        if (this.mMarkerSize != markerSize) {
            mMarkerSize = markerSize;
            initDrawableSize();
            invalidate();
        }
    }
    public void setBeginLine(Drawable beginLine) {
        if (this.mBeginLine != beginLine) {
            this.mBeginLine = beginLine;
            if (mBeginLine != null) {
                mBeginLine.setCallback(this);
            }
            initDrawableSize();
            invalidate();
        }
    }
    public void setEndLine(Drawable endLine) {
        if (this.mEndLine != endLine) {
            this.mEndLine = endLine;
            if (mEndLine != null) {
                mEndLine.setCallback(this);
            }
            initDrawableSize();
            invalidate();
        }
    }
    public void setMarkerDrawable(Drawable markerDrawable) {
        if (this.mMarkerDrawable != markerDrawable) {
            this.mMarkerDrawable = markerDrawable;
            if (mMarkerDrawable != null) {
                mMarkerDrawable.setCallback(this);
            }
            initDrawableSize();
            invalidate();
        }
    }

ÔÚÉèÖÃÖУ¬Ê×ÏÈÅжÏÊÇ·ñ¸ü¸Ä£¬Èç¹û¸ü¸ÄÄÇô¾Í¸üв¢ÖØмÆËãλÖã»ËæºóˢнçÃæ¡£

µ½ÕâÀ¿Ø¼þ²î²»¶à×¼±¸OKÁË£¬ÆäÖл¹Óкܶà¿ÉÒÔÍêÉƵĵط½£¬±ÈÈç¼ÓÉÏ¿ì½ÝÉèÖÃÑÕɫʲôµÄ£¬Ò²¿ÉÒÔ¼ÓÉÏ´óС¼ÆËãµÄ¶«Î÷¡£Í¬Ê±»¹¿ÉÒÔ¼ÓÉÏʱ¼äÏßÊÇˮƿ»¹ÊÇ´¹Ö±µÈµÈ¡£ÔÚÕâÀï¾Í²»ÀÛ׸½éÉÜÄÄЩÁË¡£ÏÂÃæÀ´¿´¿´ÈçºÎʹÓá£

ʹÓÃ

XML²¼¾Ö

ITEM²¼¾Öitem_time_line.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:paddingLeft="@dimen/lay_16"
    android:paddingRight="@dimen/lay_16"
    tools:ignore="MissingPrefix">
    <net.qiujuer.example.timeline.widget.TimeLineMarker
        android:id="@+id/item_time_line_mark"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/lay_16"
        android:paddingLeft="@dimen/lay_4"
        android:paddingRight="@dimen/lay_4"
        android:paddingTop="@dimen/lay_16"
        app:beginLine="@color/black_alpha_32"
        app:endLine="@color/black_alpha_32"
        app:lineSize="2dp"
        app:marker="@drawable/ic_timeline_default_marker"
        app:markerSize="24dp" />
    <TextView
        android:id="@+id/item_time_line_txt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:paddingBottom="@dimen/lay_16"
        android:paddingLeft="@dimen/lay_4"
        android:paddingRight="@dimen/lay_4"
        android:paddingTop="@dimen/lay_16"
        android:textColor="@color/grey_600"
        android:textSize="@dimen/font_16" />
</LinearLayout>

ÔÚÕâÀïÎÒÃÇÖ®¼äʹÓÃ˳Ðò²¼¾Ö£¬×ó±ßÊÇTimelIne¿Ø¼þ£¬ÓÒ±ßÊÇÒ»¸ö¼òµ¥µÄ×ÖÌå¿Ø¼þ£¬¾ßÌåʹÓÃÖпÉÒÔϸ»¯Ò»Ð©¡£ 
ÔÚTImeLine¿Ø¼þÖÐÎÒÃǵÄMarkÊÇʹÓõÄdrawable/ic_timeline_default_marker£»Õâ¸ö¾ÍÊÇÒ»¸ö¼òµ¥µÄԲȦ¶øÒÑ£»¶ÔÓÚ×Ô¼ºÃÀ»¯¿ÉÒÔʹÓÃÒ»ÕÅͼƬ´úÌæ»òÕ߸ü¼Ó¸´ÔӵIJ¼¾Ö£»µ±È»ÉÏÃæµÄÏßÌõ¾Í¸ü¼Ó¼òµ¥ÁË£¬¾ÍÖ±½ÓʹÓÃÑÕÉ«´úÌæ¡£

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/cyan_500" />
    <stroke
        android:width="1dp"
        android:color="@color/black_alpha_32" />
</shape>

Ö÷½çÃæXML RecyclerView

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/time_line_recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"
        android:fadeScrollbars="true"
        android:fadingEdge="none"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:overScrollMode="never"
        android:scrollbarSize="2dp"
        android:scrollbarThumbVertical="@color/cyan_500"
        android:scrollbars="vertical" />
</RelativeLayout>

ÔÚÕâÀï¾ÍÊǼÓÉÏÁËÒ»¸öRecyclerView ¿Ø¼þÔÚÖ÷½çÃæ¾ÍOK¡£

Java´úÂ벿·Ö

ÔÚ¿ªÊ¼Ö®Ç°ÏÈÀ´¿´¿´ÎÒÃǵÄÎļþ¾ßÌåÓÐЩÉñÂí¡£ 

blob.png

widgetÖоÍÊǾßÌåµÄ×Ô¶¨Òå¿Ø¼þ£¬modelÊǾßÌåµÄÊý¾ÝÄ£ÐÍ£¬adapter²¿·Ö£¬ÕâÀïÓÐÒ»¸öRecyclerviewµÄadapterÎļþ£¬ÒÔ¼°Ò»¸ö¾ßÌåµÄItem TimeLineViewHolder£¬µ±È»ÔÚÕâÀﻹ¶¨ÒåÁËÒ»¸öItemTypeÀ࣬¸ÃÀàÓÃÀ´±êʾÿ¸öItemµÄÀàÐÍ£¬±ÈÈçÍ·²¿£¬µÚÒ»¸ö£¬ÆÕͨ£¬×îºóÒ»¸ö£¬µ×²¿µÈµÈ¡£

TimeLineModel.java

package net.qiujuer.example.timeline.model;
/**
 * Created by qiujuer
 * on 15/8/23.
 */
public class TimeLineModel {
    private String name;
    private int age;
    public TimeLineModel() {
    }
    public TimeLineModel(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public int getAge() {
        return age;
    }
    public String getName() {
        return name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setName(String name) {
        this.name = name;
    }
}

Ò»¸öÃû×Ö£¬Ò»¸öÄêÁäÒ²¾ÍOK¡£

ItemType.java

package net.qiujuer.example.timeline.adapter;
/**
 * Created by qiujuer
 * on 15/8/23.
 */
public class ItemType {
    public final static int NORMAL = 0;
    public final static int HEADER = 1;
    public final static int FOOTER = 2;
    public final static int START = 4;
    public final static int END = 8;
    public final static int ATOM = 16;
}

·Ö±ð¶¨ÒåÁ˼¸¸ö¾²Ì¬Öµ£¬·Ö±ð´ú±íÆÕͨ¡¢Í·²¿¡¢µ×²¿¡¢¿ªÊ¼¡¢½áÊø¡¢Ô­×Ó£»µ±È»ÆäÖÐÓÐЩ¿ÉÒÔ²»Óö¨Òå¡£

TimeLineViewHolder.java

package net.qiujuer.example.timeline.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import net.qiujuer.example.timeline.R;
import net.qiujuer.example.timeline.model.TimeLineModel;
import net.qiujuer.example.timeline.widget.TimeLineMarker;
/**
 * Created by qiujuer
 * on 15/8/23.
 */
public class TimeLineViewHolder extends RecyclerView.ViewHolder {
    private TextView mName;
    public TimeLineViewHolder(View itemView, int type) {
        super(itemView);
        mName = (TextView) itemView.findViewById(R.id.item_time_line_txt);
        TimeLineMarker mMarker = (TimeLineMarker) itemView.findViewById(R.id.item_time_line_mark);
        if (type == ItemType.ATOM) {
            mMarker.setBeginLine(null);
            mMarker.setEndLine(null);
        } else if (type == ItemType.START) {
            mMarker.setBeginLine(null);
        } else if (type == ItemType.END) {
            mMarker.setEndLine(null);
        }
    }
    public void setData(TimeLineModel data) {
        mName.setText("Name:" + data.getName() + " Age:" + data.getAge());
    }
}

¸ÃÎļþΪRecyclerView µÄAdapterÖÐÿ¸öItemÐèҪʵÏÖµÄHolderÀà¡£ 
ÔÚ¸ÃÀàÖУ¬ÎÒÃÇÔÚ¹¹Ô캯ÊýÖÐÐèÒª´«ÈëÒ»¸ö¸ùViewͬʱ´«ÈëÒ»¸öµ±È»itemµÄ״̬¡£ 
ËæºóʹÓÃfind¡­.ÕÒµ½¿Ø¼þ£¬ÔÚÕâÀïÎÒÃÇ°ÑTextView±£´æÆðÀ´£¬¶øTimeLineViewÕÒµ½ºóÖ±½Ó½øÐгõʼ»¯ÉèÖᣠ
¸ù¾Ý´«ÈëµÄItemTypeÀ´ÅжÏÊÇ·ñÊǵÚÒ»¸ö£¬×îºóÒ»¸ö£¬ÒÔ¼°Ô­×Ó£»È»ºóÉèÖÃTimeLineViewµÄÊôÐÔ¡£ 
ÔÚÏÂÃæµÄsetData·½·¨ÖÐÎÒÃÇÏÔʾ¾ßÌåµÄModelÊý¾Ý¡£

TimeLineAdapter.java

ÊÊÅäÆ÷²¿·Ö£¬ÎÒÃÇÐèÒª×öµÄ¹¤×÷ÊÇ£»¸ù¾Ý¾ßÌåµÄÊý¾ÝäÖȾÉ϶ÔÓ¦µÄ½çÃæ¾ÍOK¡£

package net.qiujuer.example.timeline.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import net.qiujuer.example.timeline.R;
import net.qiujuer.example.timeline.model.TimeLineModel;
import java.util.List;
/**
 * Created by qiujuer
 * on 15/8/23.
 */
public class TimeLineAdapter extends RecyclerView.Adapter<TimeLineViewHolder> {
    private List<TimeLineModel> mDataSet;
    public TimeLineAdapter(List<TimeLineModel> models) {
        mDataSet = models;
    }
    @Override
    public int getItemViewType(int position) {
        final int size = mDataSet.size() - 1;
        if (size == 0)
            return ItemType.ATOM;
        else if (position == 0)
            return ItemType.START;
        else if (position == size)
            return ItemType.END;
        else return ItemType.NORMAL;
    }
    @Override
    public TimeLineViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        // Create a new view.
        View v = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.item_time_line, viewGroup, false);
        return new TimeLineViewHolder(v, viewType);
    }
    @Override
    public void onBindViewHolder(TimeLineViewHolder timeLineViewHolder, int i) {
        timeLineViewHolder.setData(mDataSet.get(i));
    }
    @Override
    public int getItemCount() {
        return mDataSet.size();
    }
}

ÔÚÕâÀïÐèÒª×ÅÖØ˵һÏ£ºÎÒ¸´Ð´ÁËgetItemViewType·½·¨£»Ôڸ÷½·¨ÖÐÎÒÃÇÐèÒªÉèÖöÔÓ¦µÄItemµÄÀàÐÍ£»ÔÚÕâÀï´«ÈëµÄÊÇitemµÄ×ø±ê£¬ÐèÒª·µ»ØµÄÊÇitemµÄ¾ßÌå״̬£¬¸Ã״̬±êʾÊÇintÀàÐÍ£»ÔÚÕâÀïÎÒʹÓõÄÊÇItemTypeµÄ¾²Ì¬ÊôÐÔ¡£

¸Ã·½·¨»áÔÚµ÷ÓÃonCreateViewHolder·½·¨Ö®Ç°µ÷Ó㻶øonCreateViewHolder·½·¨Öеĵڶþ¸ö²ÎÊýintÖµÒ²¾ÍÊÇ´ÓgetItemViewTypeÖ®ÖÐÀ´£»ËùÒÔÎÒÃÇ¿ÉÒÔÔÚÕâÀï½øÐжÔÓ¦µÄÊý¾Ý״̬±êʾ¡£

¶øÔÚonCreateViewHolder·½·¨ÖÐÎÒÃÇ·µ»ØÒ»¸ö£ºTimeLineViewHolder¾ÍOK£¬ËæºóÔÚonBindViewHolder·½·¨ÖнøÐÐÊý¾Ý³õʼ»¯²Ù×÷¡£

MainActivity.java

ÉÏÃæËùÓж¼×¼±¸ºÃÁË£¬ÏÂÃæ¾Í½øÐоßÌåµÄÏÔʾ¡£ 
ÔÚÕâÀï¾ÍÖ»Ìù³öºËÐÄ´úÂëÁË£»Æª·ùÒ²ÊÇÓÐЩ³¤¡£

    private RecyclerView mRecycler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecycler = (RecyclerView) findViewById(R.id.time_line_recycler);
        initRecycler();
    }
    private void initRecycler() {
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        TimeLineAdapter adapter = new TimeLineAdapter(getData());
        mRecycler.setLayoutManager(layoutManager);
        mRecycler.setAdapter(adapter);
    }
    private List<TimeLineModel> getData() {
        List<TimeLineModel> models = new ArrayList<TimeLineModel>();
        models.add(new TimeLineModel("XiaoMing", 21));
        models.add(new TimeLineModel("XiaoFang", 20));
        models.add(new TimeLineModel("XiaoHua", 25));
        models.add(new TimeLineModel("XiaoA", 22));
        models.add(new TimeLineModel("XiaoNiu", 23));
        return models;
    }

ÔÚÕâÀï¾ÍÊÇɵ¹ÏµÄ²Ù×÷ÁË£¬Á÷³Ì¾ÍÊÇ×¼±¸ºÃ¶ÔÓ¦µÄÊý¾Ý£¬×°½øAdapter£¬×¼±¸ºÃ¶ÔÓ¦µÄ²¼¾Ö·½Ê½£¬È»ºó¶¼ÉèÖõ½RecyclerViewÖоÍOK¡£

Ч¹û

À´¿´¿´¾ßÌåµÄЧ¹û£º

blob.png

Ч¹ûËäÈ»¼òµ¥£¬µ«ÊÇÒ²ËãÊÇÎåÔà¾ßÈ«£»ÆäÖÐÎ޷ǾÍÊǿؼþµÄ×Ô¶¨Òå¡£Õâ¸ö×Ô¶¨ÒåÊÇ¿ÉÒÔÀ©Õ¹µÄ£¬´ó¼Ò¿ÉÒÔÀ©Õ¹ÎªË®Æ½·½ÏòÊÔÊÔ¡£

´úÂë

²©¿Í´úÂ붼¿ªÔ´µ½ÏîÄ¿ÖÐÁË¡£ 
µØÖ·£ºhttps://github.com/qiujuer/BeFoot/tree/master/blog/sample/TimeLine

дÔÚ×îºó

ÎÄÕµĿªÊ¼½ØÆÁÀ´Ô´ÓÚ£º×î½üûʶùµ·¹ÄÁËÒ»¸öAPP£ÛUPMiss£Ý£¬Ò»¸ö¼òµ¥µÄÉúÈÕ£¬¼ÍÄîÈÕÌáÐÑÈí¼þ£»»¶Ó­´ó¼Ò³¢ÏÊ¡£

£ûUPMiss£ý ˼ÄîÄãµÄÏÄÌì 
ÏÂÔصØÖ·£º

  • ÷È×å

  • °Ù¶È Õâ¸öÉóºËÓÐÎÊÌ⣬Ã÷Ã÷ûÓÐÖ§¸¶µÄ¶«Î÷£¬½á¹û˵ÓÐÖ§¸¶µÄSDK´æÔÚ£¬²»µÃ²»Ëµ°Ù¶ÈµÄ×Ô¶¯ÉóºËÓкܴ󩶴¡£

  • Í㶹¼Ô Ð°æ2.0»¹ÔÚÉóºËÖУ¡

======================================================== 
×÷Õߣºqiujuer 

²©¿Í£ºblog.csdn.net/qiujuer 
ÍøÕ¾£ºwww.qiujuer.net 
¿ªÔ´¿â£ºgithub.com/qiujuer/Genius-Android 
¿ªÔ´¿â£ºgithub.com/qiujuer/Blink 
תÔØÇë×¢Ã÷³ö´¦£ºhttp://blog.csdn.net/qiujuer/article/details/47910185 
¡ª¡ª ѧ֮¿ªÔ´£¬ÓÃÓÚ¿ªÔ´£»³õѧÕßµÄÐÄ̬£¬Óë¾ý¹²Ã㣡