android开发地址选择器,Android地址选择器 类似于京东的地址选择
簡(jiǎn)介
最近東西寫的挺多的,這不又要弄一個(gè)類似于京東的地址選擇器,然后剛開始我是不愿意自己去寫的,這東西真的是浪費(fèi)時(shí)間。但是下班后回到家找了一圈沒找到一個(gè)合適的,好吧,那我就自己來(lái)封裝一個(gè)唄,反正生命在于coding,是吧~哈哈哈!先看看效果圖,不知道是不是大家想要的。區(qū)別就是京東是用在一個(gè)從下而上的彈窗里面的。
主要功能
1.大致分為三個(gè)模塊:頂部的Tab模塊,中間的移動(dòng)指示器模塊,還有就是下面的list了。
2.支持點(diǎn)擊數(shù)據(jù)后自動(dòng)跳到下一個(gè)Tab
3.支持點(diǎn)擊Tab后回到當(dāng)前Tab的狀態(tài)
4.還有就是可以隨意設(shè)置你想要的。
還是來(lái)說(shuō)說(shuō)怎么用吧。
項(xiàng)目地址:http://www.apkbus.com/thread-600090-1-1.html
集成導(dǎo)入(gradle)
1.Add the JitPack repository to your build file .Add it in your root build.gradle at the end of repositories:allprojects?{
repositories?{????????????...
maven?{?url?'https://jitpack.io'?}
}
}
2.Add the dependencydependencies?{
compile?'com.github.Blincheng:AddressSelector:v1.0.4'
}
使用
XML直接使用
android:id="@+id/address"
android:layout_width="match_parent"
android:layout_height="match_parent">
Java中使用AddressSelector?addressSelector?=?(AddressSelector)?findViewById(R.id.address);
設(shè)置Tab數(shù)量addressSelector.setTabAmount(3);
也可以不設(shè)置,默認(rèn)3級(jí)。
設(shè)置數(shù)據(jù)列表的Itme回調(diào)OnItemClickListeneraddressSelector.setOnItemClickListener(new?OnItemClickListener()?{????????????@Override
public?void?itemClick(AddressSelector?addressSelector,?CityInterface?city,?int?tabPosition)?{
}
});
設(shè)置Tab的點(diǎn)擊事件回調(diào)OnTabSelectedListeneraddressSelector.setOnTabSelectedListener(new?AddressSelector.OnTabSelectedListener()?{????????????@Override
public?void?onTabSelected(AddressSelector?addressSelector,?AddressSelector.Tab?tab)?{
}????????????@Override
public?void?onTabReselected(AddressSelector?addressSelector,?AddressSelector.Tab?tab)?{
}
});
注意,一般來(lái)說(shuō)這兩個(gè)點(diǎn)擊事件都要設(shè)置,并且數(shù)據(jù)的處理一定要搞清楚。
其他的一些屬性的設(shè)置
此處表示很憂傷,剛才不知道按了什么快捷鍵,剛寫的東西全丟了!!!不開心
實(shí)現(xiàn)
現(xiàn)在我們開始說(shuō)說(shuō)實(shí)現(xiàn)方式吧,從需求上面來(lái)講,我們需要寫出來(lái)的東西具有以下幾點(diǎn):
1.有指示器(Tab),
2.有一條會(huì)動(dòng)的橫線
3.下方有個(gè)列表
4.上方的Tab和下方的列表都是可點(diǎn)擊的。
其實(shí),從功能角度實(shí)現(xiàn)上來(lái)講,其實(shí)我們用google提供的現(xiàn)成的控件堆以下,其實(shí)也可以寫出來(lái)。比如舉個(gè)例子啊,上面的tab就用google自己的TabLayout,下方的列表就用RecyclerView,然后把數(shù)據(jù)什么的綁定以下,點(diǎn)擊事件做一下,把異常處理掉,也能出來(lái),就是說(shuō)不方便二次使用。
然后實(shí)現(xiàn)思路:我這邊直接繼承LinearLayout,然后一個(gè)一個(gè)往里面addView就好,簡(jiǎn)單粗暴。
Tab的話可以繼承TextView,Line的話繼承View應(yīng)該也行,下面的列表就直接用RecyclerView。好了,看看如何實(shí)現(xiàn)吧。
Tab的實(shí)現(xiàn)
先thinking,我們的Tab需要有文字,選中狀態(tài),然后應(yīng)該還要一個(gè)index。看代碼:/**
*?標(biāo)簽控件
*?*/
public?class?Tab?extends?TextView{
private?int?index?=?0;????????private?int?TextSelectedColor?=?Color.parseColor("#11B57C");????????private?int?TextEmptyColor?=?Color.parseColor("#333333");????????/**
*?是否選中狀態(tài)
*?*/
private?boolean?isSelected?=?false;????????public?Tab(Context?context)?{????????????super(context);
init();
}????????public?Tab(Context?context,?AttributeSet?attrs)?{????????????super(context,?attrs);
init();
}????????public?Tab(Context?context,?AttributeSet?attrs,?int?defStyleAttr)?{????????????super(context,?attrs,?defStyleAttr);
init();
}????????private?void?init(){
setTextSize(15);
}????????@Override
public?void?setText(CharSequence?text,?BufferType?type)?{????????????if(isSelected)
setTextColor(TextSelectedColor);????????????else
setTextColor(TextEmptyColor);????????????super.setText(text,?type);
}????????@Override
public?void?setSelected(boolean?selected)?{
isSelected?=?selected;
setText(getText());
}????????public?int?getIndex()?{????????????return?index;
}????????public?void?setIndex(int?index)?{????????????this.index?=?index;
}????????public?void?resetState(){
isSelected?=?false;
setText(getText());
}????????public?void?setTextSelectedColor(int?textSelectedColor)?{
TextSelectedColor?=?textSelectedColor;
}????????public?void?setTextEmptyColor(int?textEmptyColor)?{
TextEmptyColor?=?textEmptyColor;
}
}
很簡(jiǎn)單,就是重寫一下setText,然后根據(jù)選中的狀態(tài)來(lái)設(shè)置對(duì)應(yīng)的顏色即可。
實(shí)現(xiàn)Line
本來(lái)想了一下直接用View也能實(shí)現(xiàn),但是后來(lái)想想既然要移動(dòng),有點(diǎn)小動(dòng)畫,外層既然用了線性布局,這邊的橫線還有長(zhǎng)度的問(wèn)題,所以也直接用橫向的線性布局了。如下:/**
*?橫線控件
*?*/
private?class?Line?extends?LinearLayout{
private?int?sum?=?3;????????private?int?oldIndex?=?0;????????private?int?nowIndex?=?0;????????private?View?indicator;????????private?int?SelectedColor?=?Color.parseColor("#11B57C");????????public?Line(Context?context)?{????????????super(context);
init(context);
}????????public?Line(Context?context,?AttributeSet?attrs)?{????????????super(context,?attrs);
init(context);
}????????public?Line(Context?context,?AttributeSet?attrs,?int?defStyleAttr)?{????????????super(context,?attrs,?defStyleAttr);
init(context);
}????????private?void?init(Context?context){
setOrientation(HORIZONTAL);
setLayoutParams(new?LayoutParams(
LayoutParams.MATCH_PARENT,6));
setWeightSum(tabAmount);
indicator=?new?View(context);
indicator.setLayoutParams(new?LayoutParams(0,LayoutParams.MATCH_PARENT,1));
indicator.setBackgroundColor(SelectedColor);
addView(indicator);
}????????public?void?setIndex(int?index){????????????int?onceWidth?=?getWidth()/sum;????????????this.nowIndex?=?index;
ObjectAnimator?animator?=?ObjectAnimator.ofFloat(indicator,?"translationX",?indicator.getTranslationX(),?(nowIndex-oldIndex)*onceWidth);
animator.setDuration(300);
animator.start();
}????????public?void?setSum(int?sum)?{????????????this.sum?=?sum;
}????????public?void?setSelectedColor(int?selectedColor)?{
SelectedColor?=?selectedColor;
}
}
其實(shí)和Tab差不多,唯一不同的是需要之前選中的oldIndex,因?yàn)楫吘褂袀€(gè)動(dòng)畫嘛。public?void?setIndex(int?index){????????????int?onceWidth?=?getWidth()/sum;????????????this.nowIndex?=?index;
ObjectAnimator?animator?=?ObjectAnimator.ofFloat(indicator,?"translationX",?indicator.getTranslationX(),?(nowIndex-oldIndex)*onceWidth);
animator.setDuration(300);
animator.start();
}
看看這個(gè)接口,在設(shè)置index的同時(shí),把移動(dòng)的動(dòng)畫也一起做了。
AddressSelectord 實(shí)現(xiàn)
因?yàn)橹熬拖牒糜美^承LinearLayout的形式,所以也簡(jiǎn)單粗暴,直接一層一層去addView是吧,需要注意的是,這邊有個(gè)這樣的方法:/**
*?得到一個(gè)新的tab對(duì)象
*?*/
private?Tab?newTab(CharSequence?text,boolean?isSelected){
Tab?tab?=?new?Tab(mContext);
tab.setLayoutParams(new?LayoutParams(0,LayoutParams.WRAP_CONTENT,1));
tab.setGravity(Gravity.CENTER);
tab.setPadding(0,40,0,40);
tab.setSelected(isSelected);
tab.setText(text);
tab.setTextEmptyColor(TextEmptyColor);
tab.setTextSelectedColor(TextSelectedColor);
tab.setOnClickListener(this);????????return?tab;
}
看出來(lái)了吧,其實(shí)就是去創(chuàng)建需要的Tab,然后把點(diǎn)擊事件等其他參數(shù)都設(shè)置好了,主要用來(lái)AddressSelectord 內(nèi)部來(lái)創(chuàng)建Tab時(shí)候用。
然后必要的屬性還是要提供接口設(shè)置的:/**
*?設(shè)置tab的數(shù)量,默認(rèn)3個(gè),不小于2個(gè)
*?@param?tabAmount?tab的數(shù)量
*?*/
public?void?setTabAmount(int?tabAmount)?{????????if(tabAmount?>=?2){????????????this.tabAmount?=?tabAmount;
init(mContext);
}????????else
throw?new?RuntimeException("AddressSelector?tabAmount?can?not?less-than?2?!");
}
需要設(shè)置當(dāng)前tab的數(shù)量,然后看這邊又調(diào)用了init()方法,也就是說(shuō)其實(shí)這個(gè)時(shí)候AddressSelectord 又重置了。所以在init()方法中有一個(gè)removeAllViews();?需要調(diào)用。
下邊兒列表的實(shí)現(xiàn)RecyclerView
然后一開始我就在想要不要提供什么Adapter可以讓大家自己來(lái)綁定數(shù)據(jù),然后又想了想,為了簡(jiǎn)單方便大家使用,所以我覺得還是暫時(shí)不寫Adapter了。但是想想每個(gè)item的Entity不應(yīng)該是死的,畢竟大家的項(xiàng)目還是不一樣的,所以我最終采取了一種方式去實(shí)現(xiàn)。public?interface?CityInterface?{
String?getCityName();
}
就是這個(gè)接口了,大家在設(shè)置數(shù)據(jù)源的時(shí)候,盡管設(shè)置自己的,然后唯一需要注意的是大家的 Item需要去實(shí)現(xiàn)這個(gè)接口,返回我列表需要展示的文本,我用來(lái)展示列表的內(nèi)容。只能要求大家做這么一點(diǎn)點(diǎn)了。所以在設(shè)置數(shù)據(jù)的時(shí)候也要求大家這么做了。/**
*?設(shè)置列表的數(shù)據(jù)源,設(shè)置后立即生效
*?*/
public?void?setCities(ArrayList?cities)?{????????if(cities?==?null||cities.size()?<=?0)????????????return;????????if(cities.get(0)?instanceof?CityInterface){????????????this.cities?=?cities;????????????if(addressAdapter?==?null){
addressAdapter?=?new?AddressAdapter();
list.setAdapter(addressAdapter);
}
addressAdapter.notifyDataSetChanged();
}else{????????????throw?new?RuntimeException("AddressSelector?cities?must?implements?CityInterface");
}
}
不然就簡(jiǎn)單粗暴拋出throw new RuntimeException("AddressSelector cities must implements CityInterface"
這樣就好說(shuō)了,我在setOnItemClickListener可以直接返回CityInterface,就解決一切問(wèn)題了。
最后就是把要開放的接口開放一下,測(cè)測(cè)調(diào)調(diào)~
總結(jié)
然后,其實(shí)也是很簡(jiǎn)單的,就是練練手,做一些讓自己和大家都覺得方便可行的事情。如果有什么地方有問(wèn)題,或者有更好的建議真的很歡迎大家多多提出建議和意見,還有一句話就是說(shuō)沒事不要閑著,要多動(dòng)動(dòng)。
總結(jié)
以上是生活随笔為你收集整理的android开发地址选择器,Android地址选择器 类似于京东的地址选择的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: android四大组件 简书,andro
- 下一篇: android sina oauth2.