日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

RecyclerView列表控件漂亮时间线实现

發(fā)布時(shí)間:2025/4/16 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RecyclerView列表控件漂亮时间线实现 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

時(shí)間都去哪了;時(shí)間你走慢一點(diǎn)吧

很多軟件中都有時(shí)間線的東西,比如天氣,計(jì)劃,旅游等時(shí)間線最多了;具體實(shí)現(xiàn)方式很多,在本篇文章中講解一種自定義View封裝的方式實(shí)現(xiàn)時(shí)間線效果,PS:這也是面試中也時(shí)常會(huì)問到的知識(shí)點(diǎn)

1. 效果圖

2. 實(shí)現(xiàn)分析

軟件中,可以看見前面的時(shí)間線也就是線條加上圓圈組成;當(dāng)然這里的圓圈與線條也都是可以隨意換成其他的,比如圖片等等。

當(dāng)然這里最簡單的來說,是上面一個(gè)線條,然后一個(gè)圓圈,然后下面一個(gè)線條;上線條在第一條數(shù)據(jù)時(shí)不做顯示,下線條在最后一條數(shù)據(jù)時(shí)不做顯示。

這里自定義布局部分也就是把旁邊的線條與圓圈封裝到一起,并使用簡單的方法來控制是否顯示。

當(dāng)封裝好了后,與旁邊的文字部分也就是水瓶方向的線性布局了,然后設(shè)置為每一個(gè)的RecyclerView 的Item的布局也就完成了。

3. 自定義控件

控件很簡單,首先我們繼承View,取名為 TimeLineMarker 就OK。

3.1 自定義屬性

開始控件之前先準(zhǔn)備好需要的屬性。

<?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>

在這里也就準(zhǔn)備了線條的大小、開始線條、結(jié)束線條、中間標(biāo)示部分及大小。

3.2 屬性與實(shí)現(xiàn)

private int mMarkerSize = 24;private int mLineSize = 12;private Drawable mBeginLine;private Drawable mEndLine;private Drawable mMarkerDrawable;@Overrideprotected 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);}

兩個(gè)大小屬性,3個(gè)具體的Drawable,然后在onDraw方法中進(jìn)行具體的顯示也就OK。

3.3 構(gòu)造與屬性初始化

在上面我們定義了屬性,在這里我們在構(gòu)造函數(shù)中獲取XML所設(shè)置的屬性。

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

3.4 Drawable 的位置與大小初始化

屬性啥的有了,具體的Drawable 也有了,要顯示的地方調(diào)用也是OK了;但是如果沒有進(jìn)行進(jìn)行具體的位置調(diào)整這一切也都沒有意義。

@Overrideprotected 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) {// Sizeint 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 方法進(jìn)行具體的運(yùn)算,而運(yùn)算的時(shí)間點(diǎn)就是當(dāng)控件的大小改變(onSizeChanged)的時(shí)候。
在初始化中采用了一定的投機(jī)取巧;這里利用了上內(nèi)邊距與下內(nèi)邊距分別作為上線條與下線條的長度;而線條與中間的標(biāo)識(shí)都采用了水平距中。

3.5 其他設(shè)置方法

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

在設(shè)置中,首先判斷是否更改,如果更改那么就更新并重新計(jì)算位置;隨后刷新界面。

到這里,控件差不多準(zhǔn)備OK了,其中還有很多可以完善的地方,比如加上快捷設(shè)置顏色什么的,也可以加上大小計(jì)算的東西。同時(shí)還可以加上時(shí)間線是水瓶還是垂直等等。在這里就不累贅介紹哪些了。下面來看看如何使用。

3.6 使用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控件,右邊是一個(gè)簡單的字體控件,具體使用中可以細(xì)化一些。

在TImeLine控件中我們的Mark是使用的drawable/ic_timeline_default_marker;這個(gè)就是一個(gè)簡單的圓圈而已;對(duì)于自己美化可以使用一張圖片代替或者更加復(fù)雜的布局;當(dāng)然上面的線條就更加簡單了,就直接使用顏色代替。

<?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>

3.7 主界面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>

在這里就是加上了一個(gè)RecyclerView 控件在主界面就OK。

4. Java代碼部分

在開始之前先來看看我們的文件具體有些神馬。

widget中就是具體的自定義控件,model是具體的數(shù)據(jù)模型,adapter部分,這里有一個(gè)Recyclerview的adapter文件,以及一個(gè)具體的Item TimeLineViewHolder,當(dāng)然在這里還定義了一個(gè)ItemType類,該類用來標(biāo)示每個(gè)Item的類型,比如頭部,第一個(gè),普通,最后一個(gè),底部等等。

4.1 TimeLineModel.java

package net.qiujuer.example.timeline.model;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;} }

一個(gè)名字,一個(gè)年齡。

4.2 ItemType.java

package net.qiujuer.example.timeline.adapter;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; }

分別定義了幾個(gè)靜態(tài)值,分別代表普通、頭部、底部、開始、結(jié)束、原子;當(dāng)然其中有些可以不用定義。

4.3 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;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中每個(gè)Item需要實(shí)現(xiàn)的Holder類。
在該類中,我們在構(gòu)造函數(shù)中需要傳入一個(gè)根View同時(shí)傳入一個(gè)當(dāng)然item的狀態(tài)。

隨后使用find….找到控件,在這里我們把TextView保存起來,而TimeLineView找到后直接進(jìn)行初始化設(shè)置。

根據(jù)傳入的ItemType來判斷是否是第一個(gè),最后一個(gè),以及原子;然后設(shè)置TimeLineView的屬性。

在下面的setData方法中我們顯示具體的Model數(shù)據(jù)。

4.4 TimeLineAdapter.java

適配器部分,我們需要做的工作是;根據(jù)具體的數(shù)據(jù)渲染上對(duì)應(yīng)的界面。

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;public class TimeLineAdapter extends RecyclerView.Adapter<TimeLineViewHolder> {private List<TimeLineModel> mDataSet;public TimeLineAdapter(List<TimeLineModel> models) {mDataSet = models;}@Overridepublic 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;}@Overridepublic 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);}@Overridepublic void onBindViewHolder(TimeLineViewHolder timeLineViewHolder, int i) {timeLineViewHolder.setData(mDataSet.get(i));}@Overridepublic int getItemCount() {return mDataSet.size();} }

在這里需要著重說一下:我復(fù)寫了getItemViewType()方法;在該方法中我們需要設(shè)置對(duì)應(yīng)的Item的類型;在這里傳入的是item的坐標(biāo),需要返回的是item的具體狀態(tài),該狀態(tài)標(biāo)示是int類型;在這里我使用的是ItemType的靜態(tài)屬性。

該方法會(huì)在調(diào)用onCreateViewHolder方法之前調(diào)用;而onCreateViewHolder方法中的第二個(gè)參數(shù)int值也就是從getItemViewType之中來;所以我們可以在這里進(jìn)行對(duì)應(yīng)的數(shù)據(jù)狀態(tài)標(biāo)示。

而在onCreateViewHolder()方法中我們返回一個(gè):TimeLineViewHolder就OK,隨后在onBindViewHolder方法中進(jìn)行數(shù)據(jù)初始化操作。

4.5 MainActivity.java

上面所有都準(zhǔn)備好了,下面就進(jìn)行具體的顯示。 在這里就只貼出核心代碼了;篇幅也是有些長。

private RecyclerView mRecycler;@Overrideprotected 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;}

在這里就是傻瓜的操作了,流程就是準(zhǔn)備好對(duì)應(yīng)的數(shù)據(jù),裝進(jìn)Adapter,準(zhǔn)備好對(duì)應(yīng)的布局方式,然后都設(shè)置到RecyclerView中就OK

效果雖然簡單,但是也算是五臟具全;其中無非就是控件的自定義。這個(gè)自定義是可以擴(kuò)展的,大家可以擴(kuò)展為水平方向試試。

GitHub地址:https://github.com/qiujuer/BeFoot

5. UPMiss

GitHub地址:https://github.com/qiujuer/UPMiss

原文出處:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0825/3364.html

總結(jié)

以上是生活随笔為你收集整理的RecyclerView列表控件漂亮时间线实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲男女一区二区三区 | 日韩欧美自拍偷拍 | 免费超爽大片黄 | 精品少妇爆乳无码av无码专区 | 四虎黄色影院 | 黄色综合| 国色综合 | 91最新视频 | www.欧美.com | 蜜桃av噜噜一区二区三区 | 天天爱天天做 | 乱老熟女一区二区三区 | 伊人网综合网 | 人妻无码一区二区三区久久 | 深夜福利麻豆 | 超碰黑丝 | 国内精品在线观看视频 | 色哟哟日韩精品 | 天天做天天爱夜夜爽 | 天堂网一区二区三区 | 欧美激情在线免费观看 | 亚洲性图第一页 | 好吊色视频988gao在线观看 | 国产成人av免费 | 国产在线观看一区二区三区 | 日韩欧美精品在线视频 | 亚洲91久久 | 咪咪成人网 | 波多野结衣视频免费看 | 日本十八禁视频无遮挡 | 成人在线直播 | 成人特级片 | 欧美午夜精品 | 啪啪网视频 | 一道本在线播放 | 色丁香在线 | 福利精品视频 | 黄页免费视频 | 51精品国产 | 俄罗斯美女一级爱片 | 国产最新网址 | 日韩有码一区 | 日韩精品久久久久久久酒店 | youjizz.com国产 | 久久精品伦理 | 天天综合网久久综合网 | 亚洲福利专区 | 成年人网站免费观看 | 免费av网站在线 | 美脚の诱脚舐め脚视频播放 | 91免费进入 | 91精品又粗又猛又爽 | 暴操白虎 | 成人短视频在线 | 久久裸体视频 | 国产欧美日韩视频在线观看 | 中国国产黄色片 | 中国精品毛片 | 国产视频三区 | 国产初高中真实精品视频 | 女人一区二区三区 | 少妇厨房愉情理伦bd在线观看 | 日韩人妻精品在线 | 中文人妻一区二区三区 | 熟妇五十路六十路息与子 | 91亚洲专区 | 91视频合集 | 香蕉久草 | 天天做天天爱天天做 | 荡女精品导航 | 日韩三级在线观看 | 99精品在线播放 | 成人黄色网址在线观看 | 国内自拍第三页 | 豆花视频成人 | 真实的国产乱xxxx在线 | 91丨九色丨蝌蚪丨对白 | 中文字幕avav | 中文字幕久久熟女蜜桃 | 亚洲精品xxxxx | 亚洲无卡 | 自拍偷自拍亚洲精品播放 | 91视频观看 | 欧美大片a | 日本免费黄网站 | av集中营 | 超碰碰97 | 日本丰满少妇一区二区三区 | 97色网 | 国产一区二区欧美 | 女人被狂躁c到高潮喷水电影 | 99re6在线精品视频免费播放 | 国产乱码久久久久久 | 成人免费在线看片 | 手机成人在线视频 | 午夜成人在线视频 | www日日 | 偷拍超碰| 丰满人妻一区二区三区53号 |