AndroidCustomViews
方便安卓開發(fā)者使用的自定義控件庫
加入Gradle依賴
implementation 'com.ayvytr:custom-views:0.2.0'
或者
compile 'com.ayvytr:custom-views:0.2.0'
自定義控件列表
- NumberPickerView 數(shù)字選擇控件,支持多行和多種選項(xiàng)的數(shù)字選擇控件
- QuickIndexView 通訊錄右側(cè)字母索引控件
- SuperEditText 可以一鍵清空茵汰,點(diǎn)擊圖標(biāo)顯示/隱藏密碼的EditText
- SingleTextView 單行,居中,文本超出一行尾部省略的TextView
- ClearableEditText <font color=red>0.2.0新加入</font> 一鍵清空文本的EditText推姻,直接繼承AppCompatEditText
- PasswordEditText <font color=red>0.2.0新加入</font> 點(diǎn)擊或觸摸顯示/隱藏密碼的EditText拧廊,直接繼承AppCompatEditText
截圖(請看GitHub,圖片老是上傳失斪那濉)
使用和說明
NumberPickerView
NumberPickerView
是一款與android原生NumberPicker
具有類似界面以及類似功能的View
六水。
主要功能同樣是從多個(gè)候選項(xiàng)中通過上下滾動的方式選擇需要的選項(xiàng),但是與NumberPicker
相比較辣卒,有幾個(gè)主要不同點(diǎn)掷贾,下面是兩者的不同之處。
原始控件特性-NumberPicker
- 顯示窗口只能顯示3個(gè)備選選項(xiàng)荣茫;
- 在fling時(shí)阻力較大想帅,無法快速滑動;
- 在選中與非選中狀態(tài)切換比較生硬啡莉;
- 批量改變選項(xiàng)中的內(nèi)容時(shí)港准,沒有動畫效果旨剥;
- 動態(tài)設(shè)置wrap模式時(shí)(
setWrapSelectorWheel()
方法),會有“暫時(shí)顯示不出部分選項(xiàng)”的問題叉趣; - 選中位置沒有文字說明泞边;
- 代碼中不能控制選項(xiàng)滑動滾動到某一item;
自定義控件特性-NumberPickerView
- 顯示窗口可以顯示多個(gè)備選選項(xiàng)疗杉;
- fling時(shí)滑動速度較快阵谚,且可以設(shè)置摩擦力,如下代碼使得摩擦力為默認(rèn)狀態(tài)的2倍
mNumberPickerView.setFriction(2 * ViewConfiguration.get(mContext).getScrollFriction());
- 在選中與非選中的狀態(tài)滑動時(shí)烟具,具有漸變的動畫效果梢什,包括文字放大縮小以及顏色的漸變;
- 在批量改變選項(xiàng)中的內(nèi)容時(shí)朝聋,可以選擇是否采用友好的滑動效果嗡午;
- 可以動態(tài)的設(shè)置是否wrap,即冀痕,是否循環(huán)滾動荔睹;
- 選中位置可以添加文字說明,可控制文字字體大小顏色等言蛇;
- 具有在代碼中動態(tài)的滑動到某一位置的功能僻他;
- 支持
wrap_content
,支持item的padding - 提供多種屬性腊尚,優(yōu)化UI效果
- 在滑動過程中不響應(yīng)
onValueChanged()
- 點(diǎn)擊上下單元格吨拗,可以自動滑動到對應(yīng)的點(diǎn)擊對象。
- 可通過屬性設(shè)置
onValueChanged
等回調(diào)接口的執(zhí)行線程婿斥。 - 兼容NumberPicker的重要方法和接口
兼容的方法有:
setOnValueChangedListener()
setOnScrollListener()
setDisplayedValues()/getDisplayedValues()
setWrapSelectorWheel()/getWrapSelectorWheel()
setMinValue()/getMinValue()
setMaxValue()/getMaxValue()
setValue()/getValue()
兼容的內(nèi)部接口有:
OnValueChangeListener
OnScrollListener
添加的接口有:
OnValueChangeListenerInScrolling//滑動過程中響應(yīng)value change
NumberPickerView使用方法
- 通過布局聲明NumberPickerView
<cn.carbswang.android.numberpickerview.library.NumberPickerView
android:id="@+id/picker"
android:layout_width="wrap_content"
android:layout_height="240dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:background="#11333333"
android:contentDescription="test_number_picker_view"
app:npv_ItemPaddingHorizontal="5dp"
app:npv_ItemPaddingVertical="5dp"
app:npv_ShowCount="5"
app:npv_RespondChangeOnDetached="false"
app:npv_TextSizeNormal="16sp"
app:npv_TextSizeSelected="20sp"
app:npv_WrapSelectorWheel="true"/>
- Java代碼中使用:
1)若設(shè)置的數(shù)據(jù)(String[] mDisplayedValues)不會再次改變劝篷,可以使用如下方式進(jìn)行設(shè)置:(與NumberPicker的設(shè)置方式一致)
picker.setMinValue(minValue);
picker.setMaxValue(maxValue);
picker.setValue(value);
2)若設(shè)置的數(shù)據(jù)(String[] mDisplayedValues)會改變,可以使用如下組合方式進(jìn)行設(shè)置:(與NumberPicker的更改數(shù)據(jù)方式一致)
int minValue = getMinValue();
int oldMaxValue = getMaxValue();
int oldSpan = oldMaxValue - minValue + 1;
int newMaxValue = display.length - 1;
int newSpan = newMaxValue - minValue + 1;
if (newSpan > oldSpan) {
setDisplayedValues(display);
setMaxValue(newMaxValue);
} else {
setMaxValue(newMaxValue);
setDisplayedValues(display);
}
或者直接使用NumberPickerView提供的方法:
refreshByNewDisplayedValues
(String[] display)
使用此方法時(shí)需要注意保證數(shù)據(jù)改變前后的minValue值不變民宿,以及設(shè)置的display不能夠?yàn)閚ull娇妓,且長度不能夠?yàn)?。
3)添加了滑動過程中響應(yīng)value change的函數(shù)
picker.setOnValueChangeListenerInScrolling(...);
4.另外活鹰,NumberPickerView提供了平滑滾動的方法:
public void smoothScrollToValue(int fromValue, int toValue, boolean needRespond)
此方法與setValue(int)
方法相同之處是可以動態(tài)設(shè)置當(dāng)前顯示的item峡蟋,不同之處在于此方法可以使NumberPickerView
平滑的從滾動,即從fromValue
值挑選最近路徑滾動到toValue
华望,第三個(gè)參數(shù)needRespond
用來標(biāo)識在滑動過程中是否響應(yīng)onValueChanged
回調(diào)函數(shù)蕊蝗。因?yàn)槎鄠€(gè)NumberPickerView
在聯(lián)動時(shí),很可能不同的NumberPickerView
的停止時(shí)間不同赖舟,如果在此時(shí)響應(yīng)了onValueChanged
回調(diào)蓬戚,就可能再次聯(lián)動,造成數(shù)據(jù)不準(zhǔn)確宾抓,將needRespond
置為false
子漩,可避免在滑動中響應(yīng)回調(diào)函數(shù)豫喧。
另外,在使用此方法或者間接調(diào)用此方法時(shí)幢泼,需要注意最好不要在onCreate(Bundle savedInstanceState)
方法中調(diào)用紧显,因?yàn)閟croll動畫需要一定時(shí)間,如需確要在onCreate(Bundle savedInstanceState)
中調(diào)用缕棵,請使用如下方式:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//代碼省略
mNumberPickerView.post(new Runnable() {
@Override
public void run() {
//調(diào)用smoothScrollToValue()等方法的代碼
}
});
}
5.各項(xiàng)自定義屬性的說明
<declare-styleable name="NumberPickerView">
<attr name="npv_ShowCount" format="reference|integer" />//顯示的條目個(gè)數(shù)孵班,默認(rèn)3個(gè)
<attr name="npv_ShowDivider" format="reference|boolean" />//是否顯示兩條divider,默認(rèn)顯示
<attr name="npv_DividerColor" format="reference|color" />//兩條divider的顏色
<attr name="npv_DividerMarginLeft" format="reference|dimension" />//divider距左側(cè)的距離
<attr name="npv_DividerMarginRight" format="reference|dimension" />//divider距右側(cè)的距離
<attr name="npv_DividerHeight" format="reference|dimension" />//divider的高度
<attr name="npv_TextColorNormal" format="reference|color" />//未選中文字的顏色
<attr name="npv_TextColorSelected" format="reference|color" />//選中文字的顏色
<attr name="npv_TextColorHint" format="reference|color" />//中間偏右側(cè)說明文字的顏色
<attr name="npv_TextSizeNormal" format="reference|dimension" />//未選中文字的大小
<attr name="npv_TextSizeSelected" format="reference|dimension" />//選中文字的大小
<attr name="npv_TextSizeHint" format="reference|dimension" />//說明文字的大小
<attr name="npv_TextArray" format="reference" />//文字內(nèi)容招驴,stringarray類型
<attr name="npv_MinValue" format="reference|integer" />//最小值篙程,同setMinValue()
<attr name="npv_MaxValue" format="reference|integer" />//最大值,同setMaxValue()
<attr name="npv_WrapSelectorWheel" format="reference|boolean" />//設(shè)置是否wrap别厘,同setWrapSelectorWheel
<attr name="npv_HintText" format="reference|string" />//設(shè)置說明文字
<attr name="npv_EmptyItemHint" format="reference|string" />//空行的顯示文字虱饿,默認(rèn)不顯示任何文字。只在WrapSelectorWheel==false是起作用
<attr name="npv_MarginStartOfHint" format="reference|dimension" />//說明文字距離左側(cè)的距離触趴,"左側(cè)"是指文字array最寬item的右側(cè)
<attr name="npv_MarginEndOfHint" format="reference|dimension" />//說明文字距離右側(cè)的距離
<attr name="npv_ItemPaddingHorizontal" format="reference|dimension" />//item的水平padding氮发,用于wrap_content模式
<attr name="npv_ItemPaddingVertical" format="reference|dimension" />//item的豎直padding,用于wrap_content模式
<attr name="npv_RespondChangeOnDetached" format="reference|boolean" />//在detach時(shí)如果NumberPickerView正好滑動冗懦,設(shè)置
//是否響應(yīng)onValueChange回調(diào)折柠,用在一個(gè)Dialog/PopupWindow被顯示多次,
//且多次顯示時(shí)記錄上次滑動狀態(tài)的情況批狐。建議Dialog/PopupWindow在顯示時(shí)每次都指定初始值,且將此屬性置為false
<attr name="npv_RespondChangeInMainThread" format="reference|boolean" />//指定`onValueChanged`響應(yīng)事件在什么線程中執(zhí)行前塔。
//默認(rèn)為`true`嚣艇,即在主線程中執(zhí)行。如果設(shè)置為`false`則在子線程中執(zhí)行华弓。
//以下屬性用于在wrap_content模式下食零,改變內(nèi)容array并且又不想讓控件"跳動",那么就可以設(shè)置所有改變的內(nèi)容的最大寬度
<!--just used to measure maxWidth for wrap_content without hint,
the string array will never be displayed.
you can set this attr if you want to keep the wraped numberpickerview
width unchanged when alter the content list-->
<attr name="npv_AlternativeTextArrayWithMeasureHint" format="reference" />//可能達(dá)到的最大寬度寂屏,包括說明文字在內(nèi)贰谣,最大寬度只可能比此String的寬度更大
<attr name="npv_AlternativeTextArrayWithoutMeasureHint" format="reference" />//可能達(dá)到的最大寬度,不包括說明文字在內(nèi)迁霎,最大寬度只可能比此String的寬度+說明文字+說明文字marginstart +說明文字marginend 更大
<!--the max length of hint content-->
<attr name="npv_AlternativeHint" format="reference|string" />//說明文字的最大寬度
</declare-styleable>
QuickIndexView
在布局文件中加入QuickIndexView吱抚,并且加入自定義屬性,或者代碼中動態(tài)創(chuàng)建和設(shè)置自定義屬性即可
<com.ayvytr.customview.custom.index.QuickIndexView
android:id="@+id/quickIndexView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:background="#eee"
android:gravity="center"
android:lineSpacingExtra="@dimen/_10dp"
app:indexArray="@array/defaultQuickIndexViewLetters"/>
API文檔
clearIndexList() 清空字母索引.
getGravity() 獲取當(dāng)前 indexList Gravity
getIndexList() 獲取 indexList
getLineSpacing() 獲取字體上下間距值
getTextColor() 獲取字體顏色 textColor
getTextSize() 獲取字體大小
setGravity(int gravity)設(shè)置字母索引重心,只有 Gravity.TOP, Gravity.CENTER,Gravity.CENTER_VERTICAL有效考廉,也就是說只有靠上對齊或者靠中間對齊有效.
setIndexArray(String[] letterArray) 設(shè)置 indexList
setIndexList(List<String> indexList) 設(shè)置 indexList
setLineSpacing(int lineSpacing) 設(shè)置字體上下間距值
setOnLetterChangeListener(OnLetterChangeListener onLetterChangeListener) 設(shè)置字母索引變化監(jiān)聽器
setTextColor(int textColor) 設(shè)置字體顏色 textColor
setTextSize(int textSize) 設(shè)置字體大小秘豹,如果字體大小和原來的相同,或者字體大小小于0昌粤,設(shè)置不生效.
自定義屬性表
android:textColor 字體顏色
android:textSize 字體大小
android:background 背景
android:gravity 字母索引重心(實(shí)際效果只有靠頂部對齊或者居中有效)
android:lineSpacingExtra 字母索引文字上下間距
indexArray 字母索引數(shù)組
SuperEditText
API文檔
addTextChangedListener(TextWatcher watcher) 添加文本變化監(jiān)聽器
getText() 獲取當(dāng)前文本
setClearIcon(Drawable drawable) 設(shè)置清除按鈕圖標(biāo)
setClearIcon(int id) 設(shè)置清除按鈕圖標(biāo)
setFocusChangeListener(View.OnFocusChangeListener l) 設(shè)置焦點(diǎn)變化監(jiān)聽器
setHint(int id) 設(shè)置提示文本
setHint(String hint) 設(shè)置提示文本
setKeyListener(KeyListener keyListener) 設(shè)置按鍵監(jiān)聽器
setSelection(int index) 設(shè)置光標(biāo)位置
setText(int id) 設(shè)置文本
setText(String text) 設(shè)置文本
自定義屬性表
<declare-styleable name="SuperEditText">
<attr name="android:text"/>
<attr name="android:hint"/>
<attr name="android:inputType"/>
<attr name="android:enabled"/>
<attr name="android:background"/>
<attr name="android:digits"/>
<attr name="android:maxLength"/>
<attr name="android:textColor"/>
<attr name="android:textColorHint"/>
<attr name="textPaddingLeft" format="dimension"/>
<attr name="textPaddingRight" format="dimension"/>
<attr name="textPaddingTop" format="dimension"/>
<attr name="textPaddingBottom" format="dimension"/>
<attr name="textPadding" format="dimension"/>
<attr name="filterChinese" format="boolean"/>
<attr name="switchShowPassword" format="boolean"/>
<attr name="clearIcon" format="reference"/>
<attr name="showClearIcon" format="boolean"/>
<attr name="textBackground" format="reference"/>
</declare-styleable>
ClearableEditText
API 文檔
getClearTextDrawable() 獲取清除Drawable
isShowClearDrawableNoFocus() 沒有焦點(diǎn)時(shí)是否顯示清除Drawable
setClearTextDrawable(Drawable clearTextDrawable) 設(shè)置清除Drawable
setClearTextDrawable(int drawableId) 設(shè)置清除Drawable
setShowClearDrawableNoFocus(boolean showClearDrawableNoFocus) 設(shè)置沒有焦點(diǎn)時(shí)是否顯示清除Drawable
自定義屬性表
<declare-styleable name="ClearableEditText">
<attr name="showClearDrawableNoFocus" format="boolean"/> 是否在沒有焦點(diǎn)時(shí)顯示Drawable
</declare-styleable>
<h3 id="PasswordEditText">PasswordEditText</h3>
API 文檔
getHidePasswordDrawable() 獲取隱藏密碼Drawable
getShowPasswordDrawable() 獲取顯示密碼Drawable
isPasswordInputType(int inputType) 判斷輸入類型是不是密碼.
isShowDrawableNoFocus() 獲取是否在沒有焦點(diǎn)時(shí)顯示Drawable.
setClickMode(boolean clickMode) 設(shè)置點(diǎn)擊顯示/隱藏Drawable模式
setHidePasswordDrawable(Drawable hidePasswordDrawable) 設(shè)置隱藏密碼Drawable
setHidePasswordDrawable(int hidePasswordDrawableId) 設(shè)置隱藏密碼Drawable
setShowDrawableNoFocus(boolean showDrawableNoFocus) 設(shè)置是否在沒有焦點(diǎn)時(shí)顯示Drawable
setShowPasswordDrawable(android.graphics.drawable.Drawable showPasswordDrawable) 設(shè)置顯示密碼Drawable
setShowPasswordDrawable(int showPasswordDrawableId) 設(shè)置顯示密碼Drawable
自定義屬性表
<declare-styleable name="PasswordEditText">
<attr name="showPasswordDrawable" format="reference"/> 顯示密碼Drawable
<attr name="hidePasswordDrawable" format="reference"/> 隱藏密碼Drawable
<attr name="showDrawableWhenEmptyText" format="boolean"/> 當(dāng)文本為空時(shí)是否顯示Drawable
<attr name="clickMode" format="boolean"/> 點(diǎn)擊模式既绕,true:點(diǎn)擊顯示啄刹,再次點(diǎn)擊隱藏密碼;false:按下顯示凄贩,抬起隱藏密碼
<attr name="showDrawableNoFocus" format="boolean"/> 當(dāng)沒有焦點(diǎn)時(shí)是否顯示Drawable
</declare-styleable>
ChangeLog
-
0.1.0
- NumberPickerView
- QuickIndexView
- SuperEditText
- SingleTextView
-
0.2.0
- ClearableEditText
- PasswordEditText
TODO
SuperEditText自定義屬性過多誓军,需要優(yōu)化和重新設(shè)計(jì)- 加入更多自定義View
- 自定義TabLayout
- 完善測試用例(歡迎熟練Espresso等測試的大神提意見或者推薦資料)