FlowLayout 繼承於 ViewGroup ,能夠快速幫您實現 Tablayout 以及 Label 標籤,內含多種效果,幫您快速實現 APP UI 功能,讓您專一代碼架構,告別繁瑣UI。java
代碼工程:實現一個可定製化的FlowLayoutandroid
若是你也想本身寫一個,能夠參考如下幾篇文章git
實現一個可定製化的TabFlowLayout(一) -- 測量與佈局github
實現一個可定製化的TabFlowLayout(二) -- 實現滾動和平滑過渡canvas
實現一個可定製化的TabFlowLayout(三) -- 動態數據添加與經常使用接口封裝緩存
實現一個可定製化的TabFlowLayout(四) -- 與ViewPager 結合,實現炫酷效果bash
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
複製代碼
implementation 'com.github.LillteZheng:FlowHelper:v1.16'
複製代碼
首先,就是 TabFlowLayout 的效果,它的佈局支持橫豎兩種方式,首先先看支持的效果:架構
結合ViewPager | 沒有結合ViewPager |
---|---|
TabFlowLayout豎直,RecyclerView聯動效果 |
---|
除了 TabFlowLayout,還有 LAbelFlowLayout 標籤式佈局,支持自動換行app
LAbelFlowLayout 標籤式佈局 |
---|
能夠看到 目前 TabFlowLayout 支持如下效果:
主要是 TabFlowLayout 和 LabelFlowLayout 這兩個控件
首先是在 xml 中,填寫 TabFlowLayout 控件,它支持橫豎排列,默認橫向,可使用tab_orientation = "vertical" 更換成豎直排列,一個不帶效果,支持橫向的 TabFlowLayout 以下:
XML
<com.zhengsr.tablib.view.flow.TabFlowLayout
android:id="@+id/resflow"
android:layout_width="wrap_content"
android:layout_marginTop="5dp"
android:background="#6D8FB0"
android:layout_height="wrap_content"/>
複製代碼
好比要加矩形,三角形,可使用 app:tab_type 這個屬性,好比一個矩形:
<com.zhengsr.tablib.view.flow.TabFlowLayout
android:id="@+id/rectflow"
android:layout_width="wrap_content"
android:layout_marginTop="5dp"
app:tab_type="rect"
app:tab_color="@color/colorPrimary"
app:tab_height="3dp"
app:tab_width="20dp"
app:tab_margin_b="3dp"
android:background="@color/black_ff_bg"
app:tab_scale_factor="1.2"
app:tab_item_autoScale="true"
android:layout_height="wrap_content"/>
複製代碼
這裏解釋一下關鍵幾個自定參數
上面幾個爲基礎屬性,這裏填寫 tri 也能夠一樣設置。當 type 爲 round 或者 res 時,width 和 height 則能夠不填,由於要根據控件本書去適配大小。
其餘說明,能夠參看下面的自定義屬性說明。
Java
那麼,在 xml 寫好了,接着,就是在 Activity 中,這樣寫:
private void rectFlow(){
TabFlowLayout flowLayout = findViewById(R.id.rectflow);
//設置數據,這裏以 setAdapter 的形式
flowLayout.setAdapter(new TabFlowAdapter<String>(R.layout.item_msg,mTitle) {
@Override
public void onItemSelectState(View view, boolean isSelected) {
super.onItemSelectState(view, isSelected);
//選中時,能夠改變不一樣顏色,若是你的background 爲 selector,能夠不寫這個
if (isSelected){
setTextColor(view,R.id.item_text,Color.WHITE);
}else{
setTextColor(view,R.id.item_text,getResources().getColor(R.color.unselect));
}
}
@Override
public void bindView(View view, String data, int position) {
//綁定數據
setText(view,R.id.item_text,data)
.setTextColor(view,R.id.item_text,getResources().getColor(R.color.unselect));
if (position == 0){
setVisible(view,R.id.item_msg,true);
}
}
});
}
複製代碼
能夠看到,只須要設置 adapter 就好了,須要注意的是你要傳入子控件的 layout,這樣方便你自定義你的佈局,好比一個TextView 和一個紅點點。具體細節,能夠參看這個:
實現一個可定製化的TabFlowLayout(三) -- 動態數據添加與經常使用接口封裝
若是你須要使用顏色漸變的效果,TextView 換成 TabColorTextView 就能夠了,好比:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.zhengsr.tablib.view.TabColorTextView
android:id="@+id/item_text"
android:layout_width="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:text="測試"
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:textSize="14sp"
app:colortext_default_color="@color/unselect"
app:colortext_change_color="@color/colorAccent"
android:gravity="center"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/item_msg"
android:layout_width="5dp"
android:layout_height="5dp"
android:gravity="center"
android:textSize="8dp"
android:background="@drawable/shape_red_radius"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_margin="5dp"
android:visibility="gone"
/>
</android.support.constraint.ConstraintLayout>
複製代碼
結合 ViewPager 很是簡單,以下:
flowLayout.setViewPager(...) 便可.
複製代碼
爲了不卡頓,當viewpager結合fragment時,能夠有如下優化手段:
**若是您以爲viewpager切換太快,可使用 ViewPagerHelperUtils.initSwitchTime(getContext(), viewPager, 600) 改變滾動速度 **
它有幾個方法,參考這個解釋就能夠了。
/**
* 配置viewpager
* @param viewPager
* @param textId view 中 textview 的id
* @param selectedIndex 默認選中的item,初始值爲0,也能夠從第二頁或者其餘 位置
* @param unselectedColor 沒有選中的顏色 TabColorTextView 中失效
* @param selectedColor 選中的顏色 TabColorTextView 中失效
*/
public void setViewPager(ViewPager viewPager, int textId, int selectedIndex, int unselectedColor, int selectedColor) {
}
複製代碼
可能你不想在 xml 直接定死,那麼能夠直接使用 TabBean 去配置,好比使用 tab_type=res, 你的drawable 使用 shape 當移動背景的配置以下:
private void resFlow(){
final TabFlowLayout flowLayout = findViewById(R.id.resflow);
flowLayout.setViewPager(mViewPager);
/**
* 配置自定義屬性
*/
TabBean bean = new TabBean();
bean.tabType = FlowConstants.RES;
bean.tabItemRes = R.drawable.shape_round;
//點擊的動畫執行時間 ms
bean.tabClickAnimTime = 300;
bean.tabMarginLeft = 5;
bean.tabMarginTop = 12;
bean.tabMarginRight = 5;
bean.tabMarginBottom = 10;
//設置進去便可
flowLayout.setTabBean(bean);
flowLayout.setAdapter(new TabFlowAdapter<String>(R.layout.item_msg,mTitle) {
@Override
public void bindView(View view, String data, int position) {
setText(view,R.id.item_text,data);
}
@Override
public void onItemClick(View view, String data, int position) {
super.onItemClick(view, data, position);
mViewPager.setCurrentItem(position);
}
});
}
複製代碼
若是上面沒有你想要的怎麼辦?,那麼項目也支持用戶自定義,好比自定義一個白色圓點效果,只須要繼承 BaseAction 便可:
/**
* 繪製一個圓的指示器
*/
class CircleAction extends BaseAction{
private static final String TAG = "CircleAction";
@Override
public void config(TabFlowLayout parentView) {
super.config(parentView);
View child = parentView.getChildAt(0);
if (child != null) {
float l = parentView.getPaddingLeft() + child.getMeasuredWidth()/2;
float t = parentView.getPaddingTop() + child.getMeasuredHeight() - mTabHeight/2 -mMarginBottom;
float r = mTabWidth + l;
float b = child.getMeasuredHeight() - mMarginBottom;
mTabRect.set(l,t,r,b);
}
}
@Override
protected void valueChange(TabValue value) {
super.valueChange(value);
/**
* value 子控件在滾動時的 left 和 right,能夠理解爲偏移量
* TabRect 爲控件移動時的局域。
*/
//因爲自定義的,都是從left 開始算起的,因此這裏還須要加上圓的半徑
mTabRect.left = value.left + mTabWidth/2;
}
@Override
public void draw(Canvas canvas) {
canvas.drawCircle(mRect.left,mRect.top,mTabWidth/2,mPaint);
}
}
複製代碼
經過重寫 valueChange 拿到移動偏移量,而後經過 flowLayout.setAction(new CircleAction()) 便可。若是是豎直方向,拿到 value.top,value.bottom 再去寫邏輯便可。
上面的效果,能夠參考如下代碼:
前面說到,只須要把 tab_orientation 設置成 vertical 便可,相應的 當 type 爲 rect 或者 tri 時,還能夠經過 tab_tab_action_orientaion 選擇 left 仍是right 的效果:
<com.zhengsr.tablib.view.flow.TabFlowLayout
android:id="@+id/tabflow"
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:tab_type="rect"
app:tab_color="@color/colorPrimary"
app:tab_orientation="vertical"
app:tab_width="2dp"
app:tab_height="20dp"
app:tab_action_orientaion="left"
android:background="@color/page_gray_cccc"
/>
複製代碼
效果以下:
和 recyclerview 的聯動效果,能夠參考在這個:
LabelFlowLayout 豎向佈局,支持自動換行,單選、多選、長按等功能.
它的狀態變化,根據 view 的 selected 來,因此你們能夠寫 selector 當背景,或者在方法中本身設置
LabelFlowLayout 默認單選,在 xml 這樣配置:
<com.zhengsr.tablib.view.flow.LabelFlowLayout
android:id="@+id/singleflow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
複製代碼
FlowLayout 使用也使用 adapter 去配置數據:
LabelFlowLayout flowLayout = findViewById(R.id.singleflow);
final LabelFlowAdapter adapter;
flowLayout.setAdapter(adapter = new LabelFlowAdapter<String>(R.layout.item_textview,mTitle) {
@Override
public void bindView(View view, String data, int position) {
setText(view,R.id.item_text,data);
}
@Override
public void onItemSelectState(View view, boolean isSelected) {
super.onItemSelectState(view, isSelected);
TextView textView = view.findViewById(R.id.item_text);
if (isSelected) {
textView.setTextColor(Color.WHITE);
} else {
textView.setTextColor(Color.GRAY);
}
}
});
複製代碼
其實只須要配置 flowLayout.setMaxCount(3); 就能夠了,而後adapter 中重寫:
@Override
public void onReachMacCount(List<Integer> ids, int count) {
super.onReachMacCount(ids, count);
Toast.makeText(LabelActivity.this, "最多隻能選中 "+count+" 個"+" 已選中座標: "+ids, Toast.LENGTH_SHORT).show();
}
複製代碼
若是您選默認選中其中一些item,可使用 flowLayout.setSelects(2,3,5);
其實就是長按view,至於狀態的變化,由本身去寫:
private void canLongFlow(){
LabelFlowLayout flowLayout = findViewById(R.id.longflow);
flowLayout.setAdapter(new LabelFlowAdapter<String>(R.layout.item_search_layout,mTitle2) {
@Override
public void bindView(View view, String data, int position) {
setText(view,R.id.search_msg_tv,data)
.addChildrenClick(view,R.id.search_delete_iv,position);
}
@Override
public void onItemSelectState(View view, boolean isSelected) {
super.onItemSelectState(view, isSelected);
if (!isSelected){
view.setBackgroundResource(R.drawable.shape_search);
setVisible(view,R.id.search_delete_iv,false);
}
}
@Override
public void onItemClick(View view, String data, int position) {
super.onItemClick(view, data, position);
Toast.makeText(LabelActivity.this, "點擊了: "+data, Toast.LENGTH_SHORT).show();
}
@Override
public void onItemChildClick(View childView, int position) {
super.onItemChildClick(childView, position);
if (childView.getId() == R.id.search_delete_iv){
mTitle2.remove(position);
notifyDataChanged();
}
}
@Override
public boolean onItemLongClick(View view,int position) {
/**
* 置全部view 的 select 爲 false
*/
resetStatus();
view.setBackgroundResource(R.drawable.shape_search_select);
setVisible(view,R.id.search_delete_iv,true);
return super.onItemLongClick(view,position);
}
});
}
複製代碼
TabFlowLayout 和 LAbelFlowLayout 都是經過 setAdapter 的方式去加載數據的,除了支持 setText(..) ,setTextColor(..) ,setImageView 等,還支持 click 事件,具體的方法,能夠參考下面的代碼:
TabFlowLayout
名稱 | 類型 | 說明 |
---|---|---|
tab_type | rect,tri,round,color,res | tab的類型,目前支持矩形,三角形、圓角、顏色漸變、資源res |
tab_color | color | 指示器的顏色,當類型爲 rect、tri、roud是能夠經過它定義 |
tab_width | dimension | 指示器的寬度,若是不寫,則根據控件自身大小 |
tab_height | dimension | 指示器高度 |
tab_item_res | reference | 指示器的背景,好比shape,bitmap等,只對 res 起做用 |
tab_round_size | dimension | 圓角的大小,只對round起做用 |
tab_margin_l | dimension | 左偏移 |
tab_margin_t | dimension | 上偏移 |
tab_margin_r | dimension | 右偏移 |
tab_margin_b | dimension | 下偏移 |
tab_click_animTime | integer | 點擊動畫的時間,默認300ms |
tab_item_autoScale | boolean | 開啓放大縮小的效果 |
tab_scale_factor | float | 放大倍數 |
tab_orientation | integer | vertical豎直防線,horizontal橫向,默認橫向 |
tab_action_orientaion | integer | left座標,right右邊,只支持 tri、rect 兩種效果 |
tab_isAutoScroll | boolean | 是否支持自動滾動,默認爲true |
TabColorTextView
名稱 | 類型 | 說明 |
---|---|---|
colortext_default_color | color | 默認顏色 |
colortext_change_color | color | 須要漸變顏色 |
LabelFlowLayout
名稱 | 類型 | 說明 |
---|---|---|
label_maxcount | integer | 最大選擇個數 |
label_iaAutoScroll | boolean | 是否支持自動滾動 |