1. 程式人生 > >Android一個用作篩選的彈窗控制元件CustomFiltControl

Android一個用作篩選的彈窗控制元件CustomFiltControl

效果:


起初踩的坑:

    剛開始是因為專案中需要用到篩選的功能,以前也遇到過但都是其他同事做的,而我看他們的實現大多都是自己一個個的碼佈局,然後做事件處理很麻煩,還有的是通過網上的一些線性排列控制元件自己組合實現的。

    如今自己遇到了我開始想的也是通過LinearLayout動態去新增選項,title部分就是也是動態新增,一個打的LinearLayout包兩個小的,然後在小的裡面又包很多選項,但是遇到要換行的時候又需要新增一個LinearLayout,也就是但是有個問題,佈局繁瑣,得不到很好的複用。

後面突然想到了GridLayout,然後又使用了LinearLayout+GridLayout,對GridLayout是可以避免在你換行的時候去計算,只要你設定好行列,它會自動換行,這是確實實現了上面的效果,但是博主寫好了又發現不夠完美,既然GridLayout能自動換行,又可以一個站多行多列,為什麼不把title也放到GridLayout中呢,有了這個想法,又來修改,在計算行列的時候確實遇到了阻礙,不過終究是完成了,最後封裝在了popuwindow中直接呼叫。

看看主要實現吧:

package com.zzq.mack.customfiltcontrol;

import android.content.Context;
import android.graphics.Color;
import android.support.v7.widget.GridLayout;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;

import com.zzq.mack.customfiltcontrol.model.FiltModel;

import java.util.List;

/**
 * Author:xqt
 * Email:
[email protected]
* Date:2018/3/31 0031 11:24 * Description:篩選彈框 版權所有轉載請註明出處 */ public class FiltPopuWindow extends PopupWindow{ public FiltPopuWindow(Context context,View view){ //這裡可以修改popupwindow的寬高 super(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); setContentView(view); initViews(); } private void initViews() { setAnimationStyle(R.style.popwin_anim_style); //setBackgroundDrawable(new ColorDrawable(0x00000000)); setFocusable(true); setOutsideTouchable(true); } public static class Builder { private Context context; private List<FiltModel> listData; private int columnCount; private GridLayout rootGridLayout; private LinearLayout contextll; //背景顏色 private int colorBg = Color.parseColor("#F8F8F8"); private int titleTextSize = 14;//SP private int tabTextSize = 14;//SP private int titleTextColor = Color.parseColor("#333333");//標題字型顏色 private int tabTextColor = R.color.fit_item_textcolor;//選項字型顏色 private int tabBgDrawable = R.drawable.item_lable_bg_shape;//選項背景顏色 //當前載入的行數 private int row = -1; private FiltPopuWindow mFiltPopuWindow; public Builder(Context context) { this.context = context; } /** * 設定資料來源 * @return */ public Builder setDataSource(List<FiltModel> listData) { this.listData = listData; return this; } public Builder setColumnCount(int columnCount){ this.columnCount = columnCount; return this; } public Builder setColorBg(int color){ colorBg = context.getResources().getColor(color); return this; } public Builder setTitleTextSize(int titleTextSize) { this.titleTextSize = titleTextSize; return this; } public Builder setTabTextSize(int tabTextSize) { this.tabTextSize = tabTextSize; return this; } public Builder setTitleTextColor(int titleTextColor) { this.titleTextColor = titleTextColor; return this; } public Builder setTabTextColor(int tabTextColor) { this.tabTextColor = tabTextColor; return this; } public Builder setTabBgDrawable(int tabBgDrawable) { this.tabBgDrawable = tabBgDrawable; return this; } public Builder build(){ newItemLayout(getRowCount(),columnCount); for (int i = 0; i < listData.size(); i++){ ++row; TextView view = new TextView(context); view.setText(listData.get(i).getTypeName()); view.setTextColor(titleTextColor); view.setTextSize(titleTextSize); //配置列 第一個引數是起始列標 第二個引數是佔幾列 title(篩選型別)應該佔滿整行,so -> 總列數 GridLayout.Spec columnSpec = GridLayout.spec(0,columnCount); //配置行 第一個引數是起始行標 起始行+起始列就是一個確定的位置 GridLayout.Spec rowSpec = GridLayout.spec(row); //將Spec傳入GridLayout.LayoutParams並設定寬高為0或者WRAP_CONTENT,必須設定寬高,否則檢視異常 GridLayout.LayoutParams lp = new GridLayout.LayoutParams(rowSpec, columnSpec); lp.width = GridLayout.LayoutParams.WRAP_CONTENT; lp.height = GridLayout.LayoutParams.WRAP_CONTENT; lp.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); lp.bottomMargin = context.getResources().getDimensionPixelSize(R.dimen.dp_8); rootGridLayout.addView(view,lp); //新增選項 addTabs(listData.get(i),i); } return this; } private void newItemLayout(int rowCount,int columnCount){ contextll = new LinearLayout(context); contextll.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); contextll.setBackgroundColor(context.getResources().getColor(R.color.color_33000000)); contextll.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mFiltPopuWindow != null){ mFiltPopuWindow.dismiss(); //點選外部消失 } } }); rootGridLayout = new GridLayout(context); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); rootGridLayout.setOrientation(GridLayout.HORIZONTAL); rootGridLayout.setRowCount(rowCount); rootGridLayout.setColumnCount(columnCount); rootGridLayout.setBackgroundColor(colorBg); rootGridLayout.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return true; } }); int pandd = context.getResources().getDimensionPixelSize(R.dimen.dp_10); lp.weight = 1; rootGridLayout.setPadding(pandd,pandd,pandd,pandd); contextll.addView(rootGridLayout,lp); } /** * 新增選項 * @param model */ private void addTabs(final FiltModel model, final int titleIndex){ List<FiltModel.TableMode> tabs = model.getTabs(); for (int i = 0; i < tabs.size(); i++){ if (i % columnCount == 0){ row ++; } final FiltModel.TableMode tab = tabs.get(i); final TextView lable = new TextView(context); lable.setTextColor(context.getResources().getColorStateList(tabTextColor)); lable.setBackgroundDrawable(context.getResources().getDrawable(tabBgDrawable)); lable.setSingleLine(true); lable.setGravity(Gravity.CENTER); lable.setEllipsize(TextUtils.TruncateAt.MIDDLE); //這裡可以自行修改tab框框的大小 int panddT = context.getResources().getDimensionPixelSize(R.dimen.dp_2); int panddL = context.getResources().getDimensionPixelSize(R.dimen.dp_8); lable.setPadding(panddL,panddT,panddL,panddT); lable.setTextSize(tabTextSize); rootGridLayout.addView(lable,getItemLayoutParams(i,row)); lable.setText(tab.name); if (tabs.get(i) == model.getTab()){ lable.setSelected(true); } lable.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //lable.setSelected(true); if (tab != model.getTab()){ //清空上次選中 rootGridLayout.getChildAt(getIndex(model,titleIndex)).setSelected(false); //設定當前選中 model.setTab(tab); lable.setSelected(true); } } }); } } private GridLayout.LayoutParams getItemLayoutParams(int i,int row){ //使用Spec定義子控制元件的位置和比重 GridLayout.Spec rowSpec = GridLayout.spec(row,1f); GridLayout.Spec columnSpec = GridLayout.spec(i%columnCount,1f); //將Spec傳入GridLayout.LayoutParams並設定寬高為0,必須設定寬高,否則檢視異常 GridLayout.LayoutParams lp = new GridLayout.LayoutParams(rowSpec, columnSpec); lp.width = 0; lp.height = GridLayout.LayoutParams.WRAP_CONTENT; lp.bottomMargin = context.getResources().getDimensionPixelSize(R.dimen.dp_8); if(i % columnCount == 0) {//最左邊 lp.leftMargin = context.getResources().getDimensionPixelSize(R.dimen.dp_10); lp.rightMargin = context.getResources().getDimensionPixelSize(R.dimen.dp_20); }else if((i + 1) % columnCount == 0){//最右邊 lp.rightMargin = context.getResources().getDimensionPixelSize(R.dimen.dp_10); }else {//中間 lp.rightMargin = context.getResources().getDimensionPixelSize(R.dimen.dp_20); } return lp; } /** * 獲取當前選中tab的 在整個GridLayout的索引 * @return */ private int getIndex(FiltModel model,int titleIndex){ int index = 0; for (int i = 0; i < titleIndex; i++){ //計算當前型別之前的元素所佔的個數 title算一個 index += listData.get(i).getTabs().size() + 1; } //加上當前 title下的索引 FiltModel.TableMode tableModel = model.getTab(); index += model.getTabs().indexOf(tableModel) + 1; return index; } /** * 計算行數 * @return */ private int getRowCount(){ int row = 0; for (FiltModel model : listData){ //計算當前型別之前的元素所佔的個數 title算一個 row ++; int size = model.getTabs().size(); row += (size / columnCount) + (size % columnCount > 0 ? 1 : 0) ; } return row; } public FiltPopuWindow createPop(){ if (listData == null || listData.size() == 0){ try { throw new Exception("沒有篩選條件"); } catch (Exception e) { Toast.makeText(context,e.getMessage(),Toast.LENGTH_SHORT).show(); e.printStackTrace(); } return null; } mFiltPopuWindow = new FiltPopuWindow(context,contextll); return mFiltPopuWindow; } } }

通過設定columnCount的大小可以改變列數,測試2,3,4,5沒問題,只是列數越多就越擠,這是必然的。

希望對你有幫助,有問題歡迎給我留言。

這裡準備了一個demo作為參考

相關推薦

Android一個用作篩選控制元件CustomFiltControl

效果:起初踩的坑:    剛開始是因為專案中需要用到篩選的功能,以前也遇到過但都是其他同事做的,而我看他們的實現大多都是自己一個個的碼佈局,然後做事件處理很麻煩,還有的是通過網上的一些線性排列控制元件自己組合實現的。    如今自己遇到了我開始想的也是通過LinearLayo

Android自定義載入等待Dialog控制元件(仿ios效果實現)

效果圖 使用說明 1、專案下的build.gradle新增 allprojects { repositories { ... maven { url 'https://www.ji

Qt自定義按鈕控制元件

  一直以為做一個按鈕彈窗控制元件很簡單,可做起來發現並不是那麼順利,折騰了挺長時間的,先看下效果: 前言   嘗試過兩種方案,方案一:使用QToolButton控制元件,我們可以自定義一個widget,然後setMenu設定為該widget;方案二:點選一個

sobox控制元件,設定的z-index

之前試圖修改js原始碼,想了一天,但是不管用,然後在jsp直接加程式碼,竟然可以了,程式碼如下: function click(){                          var lang = 'zh';                         var

玩轉控制元件:重寫/重繪Dev中MessageBox控制元件

  很久沒有更新部落格了,本想著直接發一篇《手撕ERP》系列,從控制元件重寫、重繪,到框架搭建,再到部分模組實現+業務的。但是每次動手的時候,都覺得難以下手。直接從資料庫設計開始吧,模組設計還沒定下來,從模組設計開始吧,winform自帶控制元件和DevExpress控制元件用起來佈局實在太難看了。算了,從低

一個支援ListView的底部控制元件 PopupWindow 小例子

導語: 打造一個下滑底部彈出的視窗:PopupWindow,今日完成小小的購物車功能,現貼上方便大家複製貼上。 直接上程式碼: /** * 顯示popupWindow */

android學習筆記“RecyclerView”一個更強大的滾動控制元件

package com.example.recyclerviewtest; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import

Android一個顯示電量的小控制元件

1、目錄結構,本人是使用安卓死丟丟。 2、執行介面,輸入框中輸入數值,點選重新整理,會再電池中顯示出相應的電量 3、繪製自定義電池控制元件,首先,新建一個類BatteryState繼承View private Context mContext; private fl

android——懸浮控制元件Toast

前端 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.an

Android 自定義控制元件

原理概述 繼承自FrameLayout新增控制元件,然後開啟動畫 如果要詳細一點大體流程就是: 初始化一個彈幕View 確認彈幕View位置 新增到父佈局 開啟動畫/定時任務 動畫結束/定時任務開始執行,移除彈幕View 滾動彈幕需要動畫效果,頂部和底部的彈

QTP錄製後出框一個或多個ActiveX控制元件無法顯示的解決方法

  錄製一段指令碼程式碼,在專家檢視視窗中編輯錄制的指令碼程式碼時,會碰到彈出一個對話視窗,提示為“當前安全設定禁止執行該頁中的ActiveX 控制元件,因此,該頁可能無法正常顯示”類似的東西,而在人工操作時卻沒有這樣的現象。(如圖)        問題主要出在於QTP設定本身,之所以在編輯錄制好的指

TERSUS畫畫一樣開發軟件 顯示元件介紹-子頁面及顯示元件

軟件開發;管理軟件;無代碼軟件開發TERSUS無代碼手機電腦管理類軟件開發,其中窗口類顯示元件包括:子頁面元件(Page Dialog)、彈窗顯示元件(Modal Dialog) 子頁面元件(Page Dialog):是手機和平板移動端設計時所用到的新頁面元件,移動端是由各個頁面所組成的,在按鈕等元件中放置一

Android自定義View--翻書控制元件(一)

0.前言 最近重看了一遍封神演義,感覺QQ閱讀那個翻書的效果挺好的,準備做一個。上週五下午用了兩個小時只寫了一部分功能,以後有時間再完善 1.分析 先看效果圖 這個空間,說簡單也簡單,說難也難,簡單就在於這個效果主要就是依賴canvas的clippath才見到部分canvas,難就難在裁

android開發:自定義組合控制元件

內容介紹 本文記錄,自定義組合控制元件,為了可以程式碼複用,減少程式碼量 配置控制元件屬性檔案 開啟res/values/目錄下的arss.xml檔案,新增下面屬性程式碼,如果沒有建立arrs.xml檔案。 <?xml version="1.0" enc

android 多功能自定義畫板控制元件(用於解決特定需求)

在專案中需要做一個可以自定義軌跡,但始終只有一條線,並且支援撤銷(撤銷單位為MotionEvent的down事件到up事件),還要支援動畫預覽等功能,最重要的是能夠按照間隔畫素來獲取所有點的座標,用於專案的其他功能。 整體的思路 1.專案中的應用場景需要畫板是一個圓形的,這個好實現用canv

flutter - 點選事件(一) - 自定義一個方便的點選控制元件

android中,所有View都可以直接setOnClickListener, RN中也有TouchableHightlight這樣的控制元件可以直接套在外面,ios中也可以有UIControl 這樣的控制元件可以直接新增點選事件. 那麼flutter中有嗎? 答案自然是有. Ges

如何用 CSS 創作一個立體滑動 toggle 互動控制元件

效果預覽 線上演示 按下右側的“點選預覽”按鈕在當前頁面預覽,點選連結全屏預覽。 https://codepen.io/zhang-ou/pen/zjoOgX 可互動視訊教程 此視訊是可以互動的,你可以隨時暫停視訊,編輯視訊中的程式碼。 請用 chrome, s

Android PreferenceActivity新增Button、Textview控制元件

因為PreferenceActivity載入的layout是以PreferenceScreen為底的,所以沒辦法在layout裡面直接新增TextView之類的控制元件。 此時可以把PreferenceScreen當做一個listview,放在另一個layout中: 1. PreferenceScreen

Android : 事件分發,以及消除子控制元件和父控制元件互相的影響

效果圖 消除在上下滑的時候讓下面的listview控制元件不進行滑動 如題,先上xml的程式碼 父控制元件listview <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.Con

Android [Camera 原始碼] 元資料和控制元件(Metadata and Controls) Google官方文件(四)

Google原始碼網地址連結:https://source.android.com/devices/camera 該Google Camera的文件為系列文章,文章列表: overview Camera3 HAL Subsystem Metadata and Con