RecyclerView 列表控件中简单实现时间线
ʱ¼ä
ʱ¼ä£¬Ê±¼ä£¬Ê±¼ä°¡£»×ßÂýÒ»µã°É¡«
¿´¼ûºÜ¶àÈí¼þÖж¼ÓÐʱ¼äÏߵĶ«Î÷£¬Ã²ËÆÌìÆø°¡£¬ÂÃÓΰ¡Ê²Ã´µÄ×î¶àÁË£»¾ßÌåʵÏÖ·½Ê½ºÜ¶à£¬ÔÚ±¾ÆªÎÄÕÂÖн²½âÒ»ÖÖ×Ô¶¨ÒåView·â×°µÄ·½Ê½¡£
Ч¹û
ÏÈÀ´¿´¿´Ð§¹û¡£
·ÖÎö
Èí¼þÖУ¬¿ÉÒÔ¿´¼ûÇ°ÃæµÄʱ¼äÏßÒ²¾ÍÊÇÏßÌõ¼ÓÉÏԲȦ×é³É£»µ±È»ÕâÀïµÄԲȦÓëÏßÌõÒ²¶¼ÊÇ¿ÉÒÔËæÒâ»»³ÉÆäËûµÄ£¬±ÈÈçͼƬµÈµÈ¡£
µ±È»ÕâÀï×î¼òµ¥µÄÀ´Ëµ£¬ÊÇÉÏÃæÒ»¸öÏßÌõ£¬È»ºóÒ»¸öԲȦ£¬È»ºóÏÂÃæÒ»¸öÏßÌõ£»ÉÏÏßÌõÔÚµÚÒ»ÌõÊý¾Ýʱ²»×öÏÔʾ£¬ÏÂÏßÌõÔÚ×îºóÒ»ÌõÊý¾Ýʱ²»×öÏÔʾ¡£
ÕâÀï×Ô¶¨Òå²¼¾Ö²¿·ÖÒ²¾ÍÊÇ°ÑÅԱߵÄÏßÌõÓëԲȦ·â×°µ½Ò»Æ𣬲¢Ê¹Óüòµ¥µÄ·½·¨À´¿ØÖÆÊÇ·ñÏÔʾ¡£
µ±·â×°ºÃÁ˺ó£¬ÓëÅԱߵÄÎÄ×Ö²¿·ÖÒ²¾ÍÊÇˮƿ·½ÏòµÄÏßÐÔ²¼¾ÖÁË£¬È»ºóÉèÖÃΪÿһ¸öµÄ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´úÂ벿·Ö
ÔÚ¿ªÊ¼Ö®Ç°ÏÈÀ´¿´¿´ÎÒÃǵÄÎļþ¾ßÌåÓÐЩÉñÂí¡£
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¡£
Ч¹û
À´¿´¿´¾ßÌåµÄЧ¹û£º
Ч¹ûËäÈ»¼òµ¥£¬µ«ÊÇÒ²ËãÊÇÎåÔà¾ßÈ«£»ÆäÖÐÎ޷ǾÍÊǿؼþµÄ×Ô¶¨Òå¡£Õâ¸ö×Ô¶¨ÒåÊÇ¿ÉÒÔÀ©Õ¹µÄ£¬´ó¼Ò¿ÉÒÔÀ©Õ¹ÎªË®Æ½·½ÏòÊÔÊÔ¡£
´úÂë
²©¿Í´úÂ붼¿ªÔ´µ½ÏîÄ¿ÖÐÁË¡£
µØÖ·£º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
¡ª¡ª ѧ֮¿ªÔ´£¬ÓÃÓÚ¿ªÔ´£»³õѧÕßµÄÐÄ̬£¬Óë¾ý¹²Ã㣡