日韩性视频-久久久蜜桃-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ò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 一区二区日韩电影 | 亚洲黄色大全 | 五月深爱网| 日韩欧美在线观看一区二区三区 | 又黄又高潮的视频 | 国产一级片中文字幕 | 深夜福利在线播放 | 亚洲国产精品电影 | 91精品一区二区三区四区 | 色婷婷综合久久久久中文一区二区 | 成年人午夜视频 | 一区二区在线免费看 | 婷婷在线视频 | 五月综合色| 久久国产精品波多野结衣 | 五月婷婷综合在线观看 | 天天综合网天天综合 | 欧美另类xxxx野战 | 亚洲一区二区三区四区在线观看 | 丰满熟妇人妻中文字幕 | www.色亚洲| 免费观看在线播放 | 日韩中文字幕亚洲精品欧美 | 精品久久久蜜桃 | 欧美在线一区二区 | 欧美高清 | 亚洲精品一二区 | 国产剧情在线一区 | 中文字幕一本 | 成人黄色小说视频 | 国产黄片一区二区三区 | 国产大片在线观看 | 欧美日韩国产一级片 | 波多野结衣在线网址 | 久久av无码精品人妻系列试探 | 日本在线| 韩国色网 | www.我爱av| 麻豆网站视频 | 麻豆视频一区二区三区 | 人妖ts福利视频一二三区 | 91久久久久久 | 国产激情在线看 | 成人黄色动漫在线观看 | 91精品视频在线看 | 久久久久久亚洲中文字幕无码 | 欧美一级在线 | www色日本 | avxx| 漂亮少妇高潮午夜精品 | 亚洲码欧美码一区二区三区 | 欧洲综合视频 | 久久久久亚洲av无码a片 | 在线免费看mv的网站入口 | 国产在线欧美 | 办公室摸腿吻胸激情视频 | 日本三级全黄 | 四虎影视国产精品 | 欧美日韩精品一区二区在线播放 | 二区三区免费 | 欧美日韩人妻一区二区 | 欧美xxxx黑人 | 成人片黄网站久久久免费 | 青青草精品在线 | 亚洲一区视频 | 成人午夜视频免费看 | 精品久久久中文字幕 | 97超碰人人 | 色爽交 | 欧美va视频 | 手机免费看av片 | 免费在线观看的av | 国产毛片aaa | 双性人妖互交localhost | 强睡邻居人妻中文字幕 | 久国产| 亚洲欧美另类一区 | 秋霞福利 | 亚洲人视频 | youjizz中国少妇| 久久人人爽人人爽人人片av免费 | 成人91免费 | 亚洲一区,二区 | 日韩专区视频 | 久久99精品久久久久 | 91精品视频在线 | 日本中文在线播放 | 精品久久久噜噜噜久久久 | 正在播放国产一区 | 中文字幕一级片 | 午夜日韩在线观看 | 91精品一区二区三区在线观看 | 超碰95在线 | 青青草原亚洲视频 | 国产精品国语对白 | 高潮av在线 | 青青青青青青青青草 | 亚洲瘦老头同性xxxxx | 黑人操亚洲女 |