由于公司的手持是由原生的安卓寫的,剛好想了解一下安卓,就開始長達(dá)2周的開發(fā)過程,5個頁面,可能因為跟java有關(guān)系,本來是做前端開發(fā)的,自己雖然原來學(xué)過java,都忘光了...開發(fā)初期格外艱難..好在在自己努力,老大和小哥哥的幫助下,開發(fā)算是基本圓滿完成了,現(xiàn)在來總結(jié)一下中間遇到的問題和解決方法。
問題1: 比如數(shù)字1.23或者1.26,都進行五入的操作,變成1.3該如何實現(xiàn)?
答: 有提供內(nèi)置的BigDecimal方法,詳情可見https://segmentfault.com/a/1190000002886883,介紹的很詳細(xì)。
eg:
double value1 = 1.23;
double value2 = 1.25;
BigDecimal bd1 = new BigDecimal(value1);
BigDecimal bd2 = new BigDecimal(value2);
double result1 = bd1.setScale(1, ROUND_UP).doubleValue(); //第一個參數(shù)表示保留的小數(shù)位數(shù),第二個表示精度取值方式
double result2 = bd2.setScale(1, ROUND_UP).doubleValue();
ROUND_UP: 正數(shù)是大于等于該數(shù)的那個最近數(shù),負(fù)數(shù)是小于等于該數(shù)的那個最近數(shù)
ROUND_DOWN: 與ROUND_UP相反
還有很多其他的精度取值方式...
問題2: EditText控件,默認(rèn)是獲取光標(biāo)位置,并彈出軟鍵盤。不想要軟鍵盤,但是光標(biāo)位置希望一直保留閃爍,如何實現(xiàn)?
答:
nameText.setInputType(InputType.TYPE_NULL);
上述代碼,會隱藏軟鍵盤,但是也會讓光標(biāo)消失,不可取。
后發(fā)現(xiàn)網(wǎng)上有一種根據(jù)安卓版本,來判斷進行隱藏,看這篇鏈接:http://www.mamicode.com/info-detail-940579.html
問題3: 如何給listView中的item設(shè)置一個固定的高度?
答:問題4: 布局問題:如何實現(xiàn)左右布局?如何實現(xiàn)上部內(nèi)容固定,中間部分可滾動,按鈕始終固定在底部呢?
答:
對于左右布局,最簡單的方法就是,外層布局使用RelativeLayout,包裹的子元素分別設(shè)置android:layout_alignParentLeft="true", android:layout_alignParentRight="true"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:textSize="24sp"
android:text="左邊" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:textSize="24sp"
android:text="右邊" />
</RelativeLayout>
對于后者問題,即布局這樣寫:即
<RelativeLayout
android:layout_width="wrap_parent"
android:layout_height="wrap_parent">
<TextView
android:id="@+id/nameText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="7"
android:gravity="right"
android:textSize="22sp" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_parent"
android:layout_height="wrap_parent"
android:layout_below="@+id/nameText"
>
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/nameText"
android:scrollbars="none">
<LinearLayout
android:layout_width="wrap_parent"
android:layout_height="wrap_parent">
XXXXX.....
</LinearLayout>
</ScrollView>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="5dp"
android:orientation="horizontal">
<Button
android:id="@+id/resetbutton"
android:layout_width="100dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:background="@drawable/grey_button"
android:ems="5"
android:gravity="center"
android:text="重置"
android:textColor="@color/white"
android:textSize="24sp" />
<Button
android:id="@+id/confirmbutton"
android:layout_width="100dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:background="@drawable/light_button"
android:ems="5"
android:gravity="center"
android:text="確定"
android:textColor="@color/white"
android:textSize="24sp" />
</LinearLayout>
</RelativeLayout>
即:
(1)最外層是個RelativeLayout布局,中間可滾動部分是個ScrollView,外層包裹一個LinearLayout,為這個LinearLayout設(shè)置屬性: android:layout_below="@+id/nameText",表示該布局位于該TextView下面。
(2)ScrollView它的里面只能包裹一個子元素,通常是LinearLayout,取消滾動條的顯示:android:scrollbars="none"
(3)底部固定的按鈕外層包裹LinearLayout,為其設(shè)置
** android:layout_alignParentBottom="true"**,就可始終讓其居于底部了。
問題5: listView中,如何實現(xiàn)展示一級和二級菜單?類似于這樣:
但其實項目的需求是簡化了的,不用點擊一級菜單,再顯示或者隱藏二級菜單,而是直接一次顯示所有的一級菜單二級菜單,即像這樣:
粉色部分的是一級菜單,褐色部分的是二級菜單?
答:這個問題困擾了我一天多,后來問了技術(shù)老大,了解了一下思路就解決了...還是考慮的有問題,思路沒有打開啊!
按照上述圖示,后臺傳過來的json數(shù)據(jù)是這樣的:(list里面嵌套list)
{
list: [
{
"name": xxx1,
"usage": xxx1,
"childList": [
{
"childName": xx1
"code":xx1
},
{
"childName": xx2
"code":xx2
}
]
},
{
"name": xxx2,
"usage": xxx2,
"childList": [
{
"childName": xx3
"code":xx3
},
]
}
]
}
本來想使用網(wǎng)上有些教程的:ExpandableListView,但是后來各種報錯...只能忍痛棄之
這里還是使用的是listView,里面是listItem。
我剛開始的錯誤做法是,就是將數(shù)據(jù)重組,只要遇到childList, 遍歷childList里面的數(shù)據(jù),并放入map數(shù)組中,而數(shù)組本身父級的name,id也都塞進這個map數(shù)組中。
即最終形成的數(shù)據(jù)就是這樣:
"resetList": [
{
"childName": xx1
"code":xx1,
"name": xxx1,
"usage": xxx1,
},
{
"childName": xx2
"code":xx2,
"name": xxx1,
"usage": xxx1,
},
{
"childName": xx3
"code":xx3,
"name": xxx2,
"usage": xxx2,
},
]
這樣在遍歷時,本來第一個parent下面應(yīng)該有2個子元素,第二個parent下面有1個子元素,現(xiàn)在遍歷渲染時,即變成這樣:
明顯不對!要急哭無可奈何的時候,請教了技術(shù)老大,老大提供了這樣一種思路,就是===》
把父級元素單獨提取出來放在一個數(shù)組中,把孩子元素提取出來放到一個數(shù)組中,在listView重寫SimpleAdapter的方法時,進行判斷,如果父級元素有,設(shè)置父級元素的樣式,孩子元素隱藏;如果孩子元素有,就隱藏父級元素,設(shè)置孩子元素的樣式。
即數(shù)據(jù)結(jié)果變成這樣:
"resetList": [
{
"name": xxx1,
"usage": xxx1,
},
{
"name": xxx2,
"usage": xxx2,
},
{
"childName": xx1
"code":xx1,
},
{
"childName": xx2
"code":xx2,
},
{
"childName": xx3
"code":xx3,
},
]
Adapter接收的數(shù)據(jù)還是傳遞所有的字段名:
SimpleAdapter simpleAdapter = new abnormalTipsDetailAdapter2(AbnormalTipsDetailActivity.this,
dataList3,
R.layout.abnormal_tips_detail_item2,
new String[]{"name", "usage", "childName", "code"},
new int[]{R.id.name, R.id.usage, R.id.childName, R.id.code}
);
detail_listView.setAdapter(simpleAdapter);
在重寫的SimpleAdapter的這個方法getView再進行判斷:
public class abnormalTipsDetailAdapter2 extends SimpleAdapter {
List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
private LayoutInflater layoutInflater;
private Context context;
private int hiddenType;
public abnormalTipsDetailAdapter2(Context context, List<? extends Map<String, ?>> data,
int resource, String[] from, int[] to) {
super(context, data, resource, from, to);
this.context = context;
this.data = (List<Map<String, Object>>) data;
this.layoutInflater = LayoutInflater.from(context);
}
public final class abnormalTipsDetailComponent {
public TextView name;
public TextView usage;
public TextView childName;
public TextView code;
public RelativeLayout child; //子組件包裹層
public RelativeLayout topWrapper; //父組件包裹層
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return super.getCount();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return super.getItem(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return super.getItemId(position);
}
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub)
abnormalTipsDetailComponent abnormal_detail_component = null;
if (abnormal_detail_component == null) {
abnormal_detail_component = new abnormalTipsDetailComponent();
//獲得組件,實例化組件
convertView = layoutInflater.inflate(R.layout.abnormal_tips_detail_item2, null);
abnormal_detail_component.name = (TextView) convertView.findViewById(R.id.name);
abnormal_detail_component.usage = (TextView) convertView.findViewById(R.id.usage);
abnormal_detail_component.childName = (TextView) convertView.findViewById(R.id.childName);
abnormal_detail_component.code = (TextView) convertView.findViewById(R.id.code);
abnormal_detail_component.topWrapper = (RelativeLayout) convertView.findViewById(R.id.topWrapper);
abnormal_detail_component.child = (RelativeLayout) convertView.findViewById(R.id.child);
convertView.setTag(abnormal_detail_component);
} else {
abnormal_detail_component = (abnormalTipsDetailComponent) convertView.getTag();
}
String name = (String) data.get(position).get("name"); //父組件里才有該值
String childName = (String) data.get(position).get("childName"); //子組件里才有該值
String usage = "";
String code ="";
if(name != null) {
usage = (String) data.get(position).get("usage");
//顯示父元素
abnormal_detail_component.topWrapper.setVisibility(View.VISIBLE);
abnormal_detail_component.child.setVisibility(View.GONE);
abnormal_detail_component.name.setText(name);
abnormal_detail_component.usage.setText(usage);
}else if(childName != null) {
code = (String) data.get(position).get("code");
//顯示對應(yīng)的子元素
abnormal_detail_component.topWrapper.setVisibility(View.GONE);
abnormal_detail_component.child.setVisibility(View.VISIBLE);
abnormal_detail_component.code.setText(code + "號");
abnormal_detail_component.code.setTextColor(Color.RED);
}
return convertView;
}
}
這樣就解決了。
問題6: listView中的listItem點擊每一項時,發(fā)現(xiàn)不、無法響應(yīng)對應(yīng)的setOnItemClickListener方法?
答:查了百度發(fā)現(xiàn),這個原因是由于:
ListViewItem中有Button或者Checkable的子類控件的話,那么默認(rèn)focus是交給了子控件,而ListView的Item能被選中的基礎(chǔ)是Item本身
所以,分為2步,
(1)為有Button或者Checkable的子類控件增加屬性:
android:focusable="false"
android:clickable="false"
android:focusableInTouchMode="false"
(2)在item最外層增加屬性:
android:descendantFocusability="blocksDescendants"
問題7: 原生的android開發(fā)無論是接收數(shù)據(jù)還是傳遞數(shù)據(jù),是接收json格式的數(shù)據(jù),如何解析呢?
答:這里使用的是插件Gson來解析數(shù)據(jù)。
在app/build.gradle下,dependencies,加入該插件:
在File/Synchronize后,項目加入該包后,要解析或生成對應(yīng)的json格式的數(shù)據(jù),看這篇鏈接,https://www.cnblogs.com/liqw/p/4266209.html 寫的很詳細(xì)。
問題8: 頁面由一個頁面跳轉(zhuǎn)到另一個頁面,在原生的android中,使用的是Intent,通過
Intent intent = new Intent();
intent.setClass(MainActivity.this, OtherActivity.class);
startActivity(intent);
finish();
就可以實現(xiàn)跳轉(zhuǎn),當(dāng)然這個是未涉及到頁面?zhèn)髦担?dāng)涉及到傳值時,傳遞的值分別是String,int,或者是一個jsonArray,接收的頁面該如何解析獲得值呢?
答: 這里,這樣實現(xiàn),先把jsonArray要轉(zhuǎn)化為json字符串形式,再在接收的頁面進行解析,代碼實現(xiàn)如下:
Intent intent = new Intent();
intent.setClass(MainActivity.this, OtherActivity.class);
String waitAreaList = object.getString("list"); //這里解析jsonObject中的jsonArray的鍵,獲取對應(yīng)的值
//轉(zhuǎn)化jsonArray為json字符串,項目統(tǒng)一使用的是Gson插件解析json數(shù)據(jù)
String str = new Gson.toJson(waitAreaList);
//發(fā)送數(shù)據(jù)
intent.putExtra("extra", String.valueOf(123));
intent.putExtra("name","張三");
intent.putExtra("waitAreaList", str);
startActivity(intent);
finish();
//接收數(shù)據(jù)
Intent intent = getIntent();
int extra = intent.getIntExtra("extra", 0); //獲取int類型的數(shù)據(jù),為其默認(rèn)賦值一個0
String name = intent.getStringExtra("name"); //獲取string類型的數(shù)據(jù)
String stringData = intent.getStringExtra("waitAreaList"); //獲取json字符串?dāng)?shù)組
//判斷json字符串是否有數(shù)據(jù),有數(shù)據(jù)進行解析,還原成正常的jsonArray
if(stringData.length() != 0) {
//將JsonArray類型的Json字符串解析成對象方法
JsonParser parser = new JsonParser();
JsonArray array = parser.parse(stringData).getAsJsonArray();
....//執(zhí)行某些方法
}
問題9: 給textView字體加粗?
答: 對于英文字體,直接在對應(yīng)的xml中,為TextView設(shè)置樣式
android:textStyle="bold"
而對于中文字體,則要動態(tài)的設(shè)置:
TextView text = (TextView)findViewById(R.id.text);//或從xml導(dǎo)入
text.getPaint().setFakeBoldText(true); //字體加粗
問題10: 實現(xiàn)類似于ios的那種swithBtn效果?switchBtn放在了listView的item,如何點擊時,進行相應(yīng),請求接口?
答:
(1)對于問題1:剛開始百度了一堆,剛開始還是想搬磚,模仿網(wǎng)上的demo自定義實現(xiàn),后來技術(shù)老大說,這個東西應(yīng)該有插件,網(wǎng)上找一下,就不用自己寫很多代碼了。果斷搜索后,發(fā)現(xiàn)了插件,github網(wǎng)址:https://github.com/kyleduo/SwitchButton ,例子很詳細(xì)。
同理,還是現(xiàn)在app/build.gradle下的dependencies加入
compile 'com.github.zcweng:switch-button:0.0.3@aar'
然后在對應(yīng)要使用的xml實現(xiàn):
<com.suke.widget.SwitchButton
android:id="@+id/switchBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginTop="10dp"
android:layout_marginRight="10dp"
app:sb_checked_color="#8BC34A" //開啟的背景顏色:綠色
app:sb_enable_effect="true" //動態(tài)效果:默認(rèn)是true,開啟
app:sb_show_indicator="false" //是否顯示指示器,
app:sb_uncheck_color="#C6C7C5" /> //關(guān)閉的背景顏色:灰色
(2)對于問題2,還是考慮了一段時間的。。因為listView的數(shù)據(jù)源是通過調(diào)后端接口動態(tài)獲得的,因為listItem的文字涉及到動態(tài)的改變顏色,所以得重寫對應(yīng)的adapter方法,adapter繼承simpleAdapter方法。跟之前問題5的重寫Adapter方法是一樣的。
問題是,如果在重寫的getView方法中,點擊對應(yīng)的switchBtn按鈕,進行發(fā)起請求,代碼會報錯...那如何在本身當(dāng)前頁面的Activity中,進行請求?
在listView獲取數(shù)據(jù)后,進行
wait_area_list_view.setAdapter(simpleAdapter);
獲取list的子元素,在遍歷時,遇到問題,** ListView在setAdapter()后,getChildCount總是0的原因?**
==>網(wǎng)上查到 setAdapater是非同步(asynchronous) 的,所以類似js promise處理這種異步的請求或數(shù)據(jù),android也提供方法:加入post函式去更新ListView的ChildView即可。
這篇鏈接解決了我的問題:
http://www.cnblogs.com/linlf03/archive/2013/06/06/3120408.html
wait_area_list_view.post(new Runnable() { //這里為了解決setAdapter是非同步(asynchronous),取得的childCount總是0的問題
@Override
public void run() {
if (datalist.size() == wait_area_list_view.getChildCount()) {
int childLen = wait_area_list_view.getChildCount(); //獲取listView下的item個數(shù)
for(int i = 0; i< childLen; i++) {
RelativeLayout layout = (RelativeLayout) wait_area_list_view.getChildAt(i); //獲得子item的layout
SwitchButton switchBtn = (SwitchButton) layout.findViewById(R.id.switchBtn); //獲得switch按鈕
final TextView areaId = (TextView) layout.findViewById(R.id.areaId);
//switchBtn提供當(dāng)狀態(tài)更改時的監(jiān)聽器函數(shù)
switchBtn.setOnCheckedChangeListener(new SwitchButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(SwitchButton view, boolean isChecked) {
if(isChecked) {
int areaId = Integer.valueOf(areaId.getText().toString()); //獲得當(dāng)前改變狀態(tài)的id
changeStatus(areaId,isChecked); //進行對應(yīng)的請求
xxx..
}
}
}
}
}
}
});
//執(zhí)行對應(yīng)的后臺請求方法
private void changeStatus(int areaId,boolean useState) {
xxx...
}
解決問題~
問題11: 安卓的listView如何獲取item的EditText值?(因為:當(dāng)動態(tài)添加數(shù)據(jù)item或者刪除某個item時,由于頁面會重繪,導(dǎo)致之前填寫的edittext值被重刷消失...)
答: 這個問題還是當(dāng)時來看,困擾了我半天多,還是最后在小哥哥的幫助和理清思路下,順利解決了!真希望自己有一天,業(yè)務(wù)做的久了,在為別人解答疑惑時 都能思路清晰,經(jīng)驗豐富...
首先,要明確一點的是:listView中的item是復(fù)用的,就像我們看一個頁面中有很多條新聞一樣,不是像我們所想象的,有多少個新聞,就有多少個item渲染出來。假設(shè)頁面有1000條新聞呢?頁面會渲染卡死,體驗很差,所以按原生的安卓來寫的話,所謂復(fù)用就是: 假設(shè)listView每次就規(guī)定渲染10條item,當(dāng)我們上滑加載更多時,假設(shè)此時有3條被遮擋了,那此時要加載后續(xù)的數(shù)據(jù),安卓的實現(xiàn)是回收前3條被遮擋的item資源,在接下來的展示復(fù)用前面的3條,進行顯示,周而復(fù)始這樣循環(huán)利用,這樣確保了頁面的流暢性和性能的提升,不得不說,是一個很棒的思路和做法。
當(dāng)然,碰到的問題就是如何獲取listitem中edittext的值?
好的做法就是: 重寫listView的Adapter.getView函數(shù)方法時 ,用一個list數(shù)組來保存Editext的值,監(jiān)聽EditText值的變化,當(dāng)值有非空有變化時 ,就將對應(yīng)的值,存儲起來。其中數(shù)組的下標(biāo)就是上述listItem的position值,就是上述圖示顯示的0,1,2...
當(dāng)頁面比如有數(shù)據(jù)增加進來或者刪除時,我們此時不用擔(dān)心數(shù)據(jù)沒有,因為預(yù)先在一個數(shù)組里保存了對應(yīng)的位置和數(shù)據(jù),在頁面重繪后,再重新獲取list數(shù)組中的值,進行對應(yīng)的setText賦值,這樣就保證了數(shù)據(jù)不會丟失。
這里核心代碼主要是如下所示:
博客園的這篇鏈接: https://www.cnblogs.com/exmyth/p/3799260.html和另外一個鏈接:http://blog.sina.cn/dpool/blog/s/blog_80c69e390101g221.html 也提供幫助我很多,十分感謝!
問題12: 如何實現(xiàn)自定義dialog?
答:請戳這篇鏈接:https://blog.csdn.net/zhuwentao2150/article/details/52254579
問題13: 安卓原生系統(tǒng)中,如何讓EditText光標(biāo)集中時,始終隱藏軟鍵盤,但光標(biāo)不失去焦點?
答: 這次在stackoverflow上找到了答案。
(1)設(shè)置EditText的inputType為null,隱藏了軟鍵盤,但同時光標(biāo)也消失了... 沒啥用!
(2) 在AndroiManifest.xml中對應(yīng)的activity中,設(shè)置:android:windowSoftInputMode="stateAlwaysHidden" 然并卵..也沒啥用!
(3)當(dāng)當(dāng)當(dāng)~
最終的高票答案來了,應(yīng)該是可取的,附上代碼:
// Update the EditText so it won't popup Android's own keyboard, since I have my own.
EditText editText = (EditText)findViewById(R.id.edit_mine);
editText.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
v.onTouchEvent(event);
InputMethodManager imm = (InputMethodManager)v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
return true;
}
});
解決方法是通過onTouch時,檢測input的變化,動態(tài)的去顯示隱藏軟鍵盤。
這里我未使用的原因是,由于使用的是listview,可能listitem會有許多個,每個item中又有EditText,處理每個時,都進行動態(tài)的判斷和監(jiān)聽,無疑是比較耗性能的。
所以采取了另外的答案,就是設(shè)置在xml這樣設(shè)置:
<EditText
android:textIsSelectable="true"
...
/>
或者設(shè)置:
EditText editText = (EditText) findViewById(R.id.editText);
editText.setTextIsSelectable(true);
對于這個屬性,官方給出的解釋是:
the cursor will still be present, and you'll be able to select/copy/cut/paste, but SoftKeyboard will never show,但是要求安卓的sdk版本是在>=11以上
這樣就解決啦~中間其實還遇到問題,剛開始只是在相應(yīng)的xml中設(shè)置該屬性,一臺手持設(shè)備上表現(xiàn)正常,但另一個頁面就光標(biāo)和軟鍵盤就都消失了。。排查了一圈,發(fā)現(xiàn)應(yīng)該是手持設(shè)備sdk的版本問題導(dǎo)致的,所以最終不在xml設(shè)置屬性,在代碼里判斷版本,再設(shè)置屬性:
int version = Build.VERSION.SDK_INT;
EditText editText = (EditText) findViewById(R.id.editText);
if (version >= 11) {
editText.setRawInputType(InputType.TYPE_CLASS_TEXT);
editText.setTextIsSelectable(true);
} else {
editText.setRawInputType(InputType.TYPE_NULL);
editText.setFocusable(true);
}
問題14: listView的listItem中,使用了checkbox控件,由于checkbox的獲取焦點優(yōu)先級高于listItem本身的setOnItemClickListener,所以希望當(dāng)點擊listitem時,也能選中或者不選中對應(yīng)的checkbox,而不是只能點擊checkbox進行選中非選中?
答:這里搜索了一圈,后來有篇博客提供了很好的答案: http://blog.sina.com.cn/s/blog_6fff321b0100otwo.html
即布局大概是這樣的:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/check_box_list_item"
android:minHeight="45dp"
android:orientation="horizontal"
android:descendantFocusability="blocksDescendants"
>
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/boilBox"
style="@style/BoilAreaCheckBox"
android:background="@drawable/selector"
android:button="@null"
android:checked="false"
android:focusable="false"
android:layout_marginTop="5dp"
android:layout_marginLeft="20dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:textSize="20sp"
android:id="@+id/areaName"
android:layout_marginTop="5dp"
/>
/>
對應(yīng)的activity中這樣寫:
checkbox_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
// LinearLayout layout = (LinearLayout) adapterView.getChildAt(position);
// CheckBox checkBox = (CheckBox) layout.getChildAt(0);
CheckBox checkBox = (CheckBox) view.findViewById(R.id.boilBox);
checkBox.setChecked(!checkBox.isChecked());
}
});
注意:
(1): 這里的 checkbox_list是listView的id名稱;
(2): 這里setItem時,去動態(tài)監(jiān)聽布局,拿到每次點擊的positon對應(yīng)的LinearLayout; 由于CheckBox控件都是布局的第一個元素,所以是 CheckBox checkBox = (CheckBox) layout.getChildAt(0);
(3): 通過setChecked控制選中,通過isChecked()判斷當(dāng)前是否選中
(4): checkBox獲取焦點的優(yōu)先級,不要搶占點擊listitem的優(yōu)先級,即對于checkbox設(shè)置屬性:
android:checked="false"
android:focusable="false"
而對于listItem層級,設(shè)置屬性
android:descendantFocusability="blocksDescendants"
這里在之后發(fā)現(xiàn)大bug!!注意注意!!,就是listview中使用checkbox,當(dāng)數(shù)據(jù)多時,由于listview本身的復(fù)用item的特性,導(dǎo)致getChildAt會報空指針!!
所以之前的代碼用斜杠注釋掉了,現(xiàn)在點擊某一個item下的checkbox,直接在setOnItemClickListener中找到當(dāng)前view下的checkBox,之后再進行選中非選中操作。
問題15: 如果讓edittext的光標(biāo)始終集中在輸入文字的末尾?
答: 添加該行代碼:
EditText et = (EditText)R.id.findViewById(R.id.edit);
et.setSelection(et.getText().length()); //讓光標(biāo)在文字末尾
問題16: 當(dāng)listview中使用了checkbox時,由于listitem的復(fù)用的特性,導(dǎo)致勾選的狀態(tài)混亂或者勾選狀態(tài)消失,如何解決?
答:雖然這個問題百度和stackoverflow上一搜一大堆,但是質(zhì)量良莠不齊的,耽誤了2天的時間搜索答案,結(jié)果中午吃飯的時候突然有了思路,外加查到一篇好的博文,終于解決問題!!大塊人心!!
這里好好總結(jié)處理一下:
這篇博文: https://blog.csdn.net/jdsjlzx/article/details/7318659 幫助很多!強烈建議一看啊!
我最終的解決方法也是模仿文章的方法來做的:
這里,首先重寫Adapter類,繼承自SimpleAdapter,這里,用一個HashMap<Integar,Boolean>來保存checkbox的勾選狀態(tài),默認(rèn)初始都為false
public class BindBoidAreaAdapter extends SimpleAdapter {
List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
private LayoutInflater layoutInflater;
private Context context;
private static HashMap<Integer, Boolean> isSelected = null; //用來控制CheckBox的選中狀況
public BindBoidAreaAdapter(Context context, List<? extends Map<String, ?>> data,
int resource, String[] from, int[] to) {
super(context, data, resource, from, to);
this.context = context;
this.data = (List<Map<String, Object>>) data;
this.layoutInflater = LayoutInflater.from(context);
isSelected = new HashMap<Integer, Boolean>();
initStatus();
}
// 初始化isSelected的數(shù)據(jù),默認(rèn)都為未勾選狀態(tài)
private void initStatus() {
for (int i = 0; i < data.size(); i++) {
getIsSelected().put(i, false);
}
}
//向activity暴露checkbox的勾選狀態(tài),返回這個HashMap
public static HashMap<Integer, Boolean> getIsSelected() {
return isSelected;
}
public final class bindBoidAreaComponent {
public CheckBox boilBox;
public TextView areaName;
public TextView areaId;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return super.getCount();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return super.getItem(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return super.getItemId(position);
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final int pos = position;
// TODO Auto-generated method stub)
bindBoidAreaComponent bind_boil_area = null;
if (bind_boil_area == null) {
bind_boil_area = new bindBoidAreaComponent();
//獲得組件,實例化組件
convertView = layoutInflater.inflate(R.layout.check_box_list_item, null);
bind_boil_area.boilBox = (CheckBox) convertView.findViewById(R.id.boilBox);
bind_boil_area.areaName = (TextView) convertView.findViewById(R.id.areaName);
bind_boil_area.areaId = (TextView) convertView.findViewById(R.id.areaId);
convertView.setTag(bind_boil_area);
} else {
bind_boil_area = (bindBoidAreaComponent) convertView.getTag();
}
bind_boil_area.boilBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
getIsSelected().put(pos,isChecked); //用來解決listView在滾動時,checkbox狀態(tài)混亂的問題
}
});
//綁定數(shù)據(jù)
String areaName = (String) data.get(position).get("areaName");
Integer areaId = (Integer) data.get(position).get("areaId");
bind_boil_area.areaName.setText(areaName);
bind_boil_area.areaId.setText("" + areaId);
//根據(jù)isSelected設(shè)置checkbox的選中
bind_boil_area.boilBox.setChecked(getIsSelected().get(pos));
return convertView;
}
}
上述adapter方法中,最重要的幾個方法,
(1)一個是構(gòu)建HashMap,初始化checkbox的state, 方法為initStatus();
(2) 如果要將adapter中設(shè)置的HashMap,在activity中 也能使用,則要寫一個public static方法,返回這個HashMap,之后就可以在activity中,BindBoidAreaAdapter.getIsSelected(),訪問得到我們設(shè)置的HashMap。(當(dāng)時思路就卡在這里了!不知道如果去訪問adpater中的設(shè)置的這個數(shù)據(jù),恩,還是有收獲的)
這里就涉及到android的static,是靜態(tài)變量,一般靜態(tài)變量用的不多,靜態(tài)常量用的比較多。
static即始終會保存在內(nèi)存里,不會隨著activity的銷毀被回收,會占用內(nèi)存。static的使用,是為了讓多個對象共用一份空間,節(jié)省內(nèi)存,由于不正確的操作或者編碼不規(guī)范,會造成內(nèi)存泄露。。但這里先不深入那么多...
(3)特別注意,中間的針對于checkbox的setOnCheckedChangeListener監(jiān)聽的方法中,
getIsSelected().put(pos,isChecked); //該行代碼,、在滾動時,動態(tài)設(shè)置checkbox的選中非選中為true 或者false
和
//根據(jù)isSelected設(shè)置checkbox的選中
bind_boil_area.boilBox.setChecked(getIsSelected().get(pos));
再來看Activity方法中,接收的數(shù)據(jù)是這樣的,后臺會傳一份全部的數(shù)據(jù)list,和(如果之前有勾選checkbox)傳遞一個checkedList數(shù)組,反之傳來的checkedList為空字符串。
我這里具體的做法是,請求數(shù)據(jù)獲得全部的數(shù)據(jù)后,先去動態(tài)繪制出這個listview
private void getData() {
xxx....
setAllCheckViews();
//這里前面加判斷,如果有勾選的list,則去顯示勾選的list
checkbox_list.post(new Runnable() { //這里為了解決setAdapter是非同步(asynchronous),取得的childCount總是0的問題
@Override
public void run() {
checkedBoxView(checkedArray);
}
});
}
//設(shè)置全部的checkbox名稱與id
private void setAllCheckViews() {
int allcount = allArray.size();
for (int i = 0; i < allcount; i++) {
Map<String, Object> map = new HashMap<String, Object>();
String areaName = allArray.get(i).getAsJsonObject().get("areaName").getAsString();
int areaId = allArray.get(i).getAsJsonObject().get("areaId").getAsInt();
map.put("areaName", areaName);
map.put("areaId", areaId);
allList.add(map);
}
simpleAdapter = new bindBoidAreaAdapter(BindBoilAreaActivity.this,
allList,
R.layout.check_box_list_item,
new String[]{"areaName", "areaId"},
new int[]{R.id.areaName, R.id.areaId}
);
checkbox_list.setAdapter(simpleAdapter);
}
然后,listView中的各個item顯示出來后,再進行具體的勾選狀態(tài):
private void checkedBoxView(JsonArray checkedArray) {
int allCount = allArray.size();
int checkedCount = checkedArray.size();
for (int i = 0; i < allCount; i++) {
for (int j = 0; j < checkedCount; j++) {
int allId = allArray.get(i).getAsJsonObject().get("areaId").getAsInt();
int checkId = checkedArray.get(j).getAsJsonObject().get("areaId").getAsInt();
if (allId == checkId) { //勾選對應(yīng)checkbox
BindBoidAreaAdapter.getIsSelected().put(i, true); //這里就是通過雙重循環(huán)比對id,若id相同,則設(shè)置對應(yīng)的checkbox為選中
}
}
}
simpleAdapter.notifyDataSetChanged(); //重繪一下頁面,否則頁面觀察不到變化!
}
上述代碼中,只有通過:
BindBoidAreaAdapter.getIsSelected().put(i, true);
該行代碼,BindBoidAreaAdapter這個類才能訪問到里面構(gòu)造的靜態(tài)方法getIsSelected,從而拿到BindBoidAreaAdapter類中預(yù)先定義好的靜態(tài)變量hashMap,進行對應(yīng)的更改操作。
但很奇怪,在自己的理解中,在類中定義一個public的方法,按理說不需要static修飾,在activity中實例化這個類的對象,就可以通過對象訪問到該方法了。
但當(dāng)我去掉BindBoidAreaAdapter中對于isSelected這個hashMap的static的修飾,同時也去掉對于方法名getIsSelected的static的修飾時,Activity中
BindBoidAreaAdapter.getIsSelected().put(i, true); 這行代碼就會報錯,說Non-static method 'getIsSelected' cannot be referenced from a static context.
即后來問了小哥哥,討論了一下,看書了解到,即只有靜態(tài)方法可以訪問到自身類中的靜態(tài)域
就比如這個例子
public static int getId() { return nextId; // return static field }
此時假設(shè)包含這個靜態(tài)方法getId的類叫Employee,我們就可以通過
int id = Employee.getId(); //獲得數(shù)據(jù)
可以使用對象調(diào)用靜態(tài)方法,比如我們此時可以
BindBoidAreaAdapter bindBoidAreaAdapter = null; //bindBoidAreaAdapter為BindBoidAreaAdapter的對象
在循環(huán)中,再
bindBoidAreaAdapter.getIsSelected().put(i, true);
不過書上講,這種方式很容易造成混淆,原因是getIsSelected得到的結(jié)果跟bindBoidAreaAdapter沒有任何關(guān)系。
書上建議:
建議使用類名,而不是對象來調(diào)用靜態(tài)方法。
書上同樣指出,以下兩種情況使用靜態(tài)方法:
(1)一個方法不需要訪問對象狀態(tài),其所需參數(shù)都是通過顯式參數(shù),如Math.pow(x,a),就是一個靜態(tài)方法
(2)一個方法只需要訪問類中的靜態(tài)域,比如我們之前所寫代碼的:BindBoidAreaAdapter.getIsSelected().put(i, true);
這里原來自己老的做法是,雙重循環(huán)遍歷,然后
private void checkedBoxView(JsonArray checkedArray) {
int allCount = allArray.size();
int checkedCount = checkedArray.size();
for (int i = 0; i < allCount; i++) {
for (int j = 0; j < checkedCount; j++) {
int allId = allArray.get(i).getAsJsonObject().get("areaId").getAsInt();
int checkId = checkedArray.get(j).getAsJsonObject().get("areaId").getAsInt();
LinearLayout layout = (LinearLayout) checkbox_list.getChildAt(i);
CheckBox checkBox = (CheckBox) layout.findViewById(R.id.boilBox);
if(allId = checkId) {
checkBox.setChecked(true);
}
}
}
}
這里當(dāng)時就報nullPointerException了,比如現(xiàn)在allArray現(xiàn)在是9個,而頁面可視區(qū)域只有7個,getChildAt最多定位的postion只有7,當(dāng)循環(huán)遍歷到8和9時,listview找不到,就報錯了。。。
解決報錯的方法:即網(wǎng)上說的很多,positon要為可視區(qū)域的position,有2種解決方法:
一種是: 即最外層的循環(huán),allCount并非 allArray.size(),而是listView可視區(qū)域的數(shù)量,
int allCount = checkbox_list.getLastVisiblePosition() - checkbox_list.getFirstVisiblePosition();
另一種是:內(nèi)部的getChildAt,使用,
int positon = i - checkbox_list.getFirstVisiblePosition();
LinearLayout layout = (LinearLayout) checkbox_list.getChildAt(positon);
雖然上述2種做法可以解決不報錯了,但是還是沒有解決勾選對應(yīng)的應(yīng)選中的checkbox,還是會復(fù)用item,checkbox的狀態(tài)混亂,所以。。舍棄,但記錄下來,為防止以后碰到類似問題。
一個bug解決了2天多...最終有學(xué)到東西,還是挺好的,希望自己之后安卓這部分做好,還是回歸前端,好好夯實前端基礎(chǔ)吧。
問題17: 如何讓ScrollView下的內(nèi)容都能居中顯示呢?
答:百度搜了一圈,沒有很靠譜的,后來同樣是在stackoverflow上找到答案。
問題描述,類似于這樣:
好幾個優(yōu)質(zhì)的答案,我選用的是第一種,即設(shè)置linearlayout的中的屬性
android:gravity="center_horizontal"
android:layout_gravity="center_horizontal"
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scrollView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingTop="12dp"
android:paddingBottom="20dp"
android:scrollbarStyle="outsideOverlay" >
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center"
android:gravity="center">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="check"
android:gravity="center_vertical|center_horizontal"/>
</LinearLayout>
</ScrollView>
第二種好的做法是,在ScrollView外面再包裹一層Relativelayout,為了讓其生效,首先要設(shè)置ScrollView下的layout_height:wrap_content,
其次,對于ScrollView,實際上此時為RelativeLayout的子元素,要使其居中,設(shè)置屬性 android:layout_centerVertical="true"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ScrollView
android:id="@+id/scrollView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true" >
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="wrap_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
</RelativeLayout>
但個人感覺這樣,一層層嵌套包裹,實際上頁面渲染會變慢,最好的方式實際上是頁面結(jié)構(gòu)越簡單越好。
問題18: 遇到一個問題,就是安卓的頁面中有EditText控件,在它的下面又有spinner控件,EditText控件 在第一次輸入后,按Enter鍵表現(xiàn)正常,當(dāng)?shù)诙屋斎氚磂nter鍵,則光標(biāo)會定位到spinner控件上,如何處理?
答: 這里也不知道是不是手持設(shè)備的原因,最終是為EditText控件設(shè)置屬性: android:nextFocusDown="@id/soakEdit",即下次光標(biāo)定位還是在其本身,就可以解決這個問題了。
<EditText
android:id="@+id/soakEdit"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:background="@null"
android:ems="8"
android:hint="@string/soak_scan"
android:nextFocusDown="@id/soakEdit"
android:textSize="23sp" />
問題19: 使用原生安卓的button時,button使用的是一張背景圖。當(dāng)發(fā)起請求,由于請求是異步的,得到結(jié)果有延遲,導(dǎo)致用戶以為沒有效果,會多點按鈕,體驗效果差。更好的體驗是:發(fā)起請求有個loading的狀態(tài),得到返回結(jié)果后隱藏這個這個loading狀態(tài)。
答:開始考慮這個問題的時候,跟之前做過的switchButton一樣,首先應(yīng)該考慮的是有無這樣的button插件實現(xiàn)。
網(wǎng)上搜到了這種效果的progressButton,但是在設(shè)置build.gradle,該插件的依賴時,各種報錯,沒有辦法解決,所以最終棄之。
后來在stackoverflow上,找到提供思路的答案,即使用安卓原生的組件progressBar,具體鏈接,參考:https://stackoverflow.com/questions/12559461/how-to-show-progress-barcircle-in-an-activity-having-a-listview-before-loading
這個高票答案寫的很棒,我也基本上按照這個思路來:
即:
- 先在xml里設(shè)置好ProgressBar的布局,默認(rèn)隱藏;
- 在activity里,初始化該ProgressBar
- 發(fā)送請求時,顯示這個ProgressBar,得到請求結(jié)果時,隱藏該ProgressBar。
中間出現(xiàn)的問題,可能集中在布局這里,原來只是button設(shè)置background為drawable下的圖片資源,ProgressBar也可以放在按鈕的前面,但是問題是分離了,loading未包含在btn里面。
后來好的解決方法:
即將ProgressBar和Button都放在一個Linearlayout布局中,就像這樣:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@drawable/bh_button_shape"
>
<ProgressBar
android:id="@+id/pbNormal"
android:layout_width="35dp"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:visibility="invisible"
/>
<Button
android:id="@+id/bindbutton"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="@android:color/transparent"
android:text="綁定"
android:layout_marginRight="45dp"
android:textColor="@color/white"
android:textSize="24sp" />
</LinearLayout>
具體步驟:
1、為LinearLayout設(shè)置背景為原來的button背景圖,orientation設(shè)置為水平horizontal
2、ProgressBar默認(rèn)不顯示
3、Button設(shè)置背景為透明,android:background="@android:color/transparent"
4、具體再調(diào)整樣式細(xì)節(jié)。
這中間還遇到一個問題,如何讓一個按鈕始終居于頁面底部呢?
兩種方式:
第一種:
如果是Linearlayout布局,則給上面的Linearlayout設(shè)置android:layout_weight="1" ,這樣可以讓底部的button到達(dá)底部。
第二種:
使用Relativelayout布局,對于Button設(shè)置屬性=》,android:layout_alignParentBottom="true"
問題20: 如何讓兩個TextView在頁面上實現(xiàn)左右平分布局?
答:百度查的答案都良莠不齊,后來在stackoverflow上找到答案。
總結(jié)一下,有2種方案:
第一種:
用一個Linearlayout包裹這2個TextView,設(shè)置layout_width為fill_parent,給子TextView要么設(shè)置layout_weight為1要么都不設(shè)置這個layout_weight。
代碼如下:
<LinearLayout
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
orientation = "horizontal">
<TextView
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:text = "Text 1"
/>
<TextView
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:text = "Text 2"
/>
</LinearLayout>
第二種:(比較高票,我也使用的這個,實現(xiàn)了平分布局的效果)
代碼如下:
<RelativeLayout
android:layout_width = "fill_parent"
android:layout_height = "wrap_content">
<LinearLayout
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:orientation="horizontal"
android:weightSum = "2">
<TextView
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:text = "YOUR FIRST TEXT"
android:weight = "1"
/>
<TextView
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:text = "YOUR SECOND TEXT"
android:weight = "1"
/>
</LinearLayout>
</RelativeLayout>
該方法的要點有3個:
- 設(shè)置他們的layout_width均為fill_parent
- 給外層包裹的Linearlayout設(shè)置權(quán)重總和android:weightSum = "2",android:orientation="horizontal"
- 設(shè)置子TextView的android:weight = "1"
答案這么介紹這個weight sum屬性:
the weight sum will be used to measured the portion of the textview like if you give the weight sum 3 and give 1 textview weight = 2 and another textview weight = 1 the layout will be 2/3 (66.666%) and 1/3 (33.3333%) so if you set it 2 and give every textview weight = 1 it should be 50% and 50%
問題21: 如何將一個JSONArray中的值取出來,添加到一個字符串?dāng)?shù)組里?如何將一個字符串?dāng)?shù)組轉(zhuǎn)化為以逗號分隔的字符串?
答:同樣是在stackoverflow上找到答案,國外的answer,真是很棒~
這里,原來百度查到的,將字符串?dāng)?shù)組變?yōu)樽址梢杂肧tringUtils.join(',',strArray);
但后來查到: StringUtils.join(',',strArray) 是Jave 8里添加的一個方法,所以不能用在Android里。
可以用TextUtils.join來代替,
String result = TextUtils.join(", ", list); //list
所以最終所有問題的實現(xiàn),代碼如下可以解決:
ArrayList<String> stringArr = new ArrayList<String>();
JSONArray jsonArray = object.getJSONArray("list");
int count = jsonArray.length();
for(int i = 0; i < count;i++) {
String code = jsonArray.getJSONObject(i).getString("code");
stringArr.add(code);
}
String[] stringArr = stringArr.toArray(new String[stringArr.size()]);
String bucketStr = TextUtils.join(",",stringArr);
問題22: (1)安卓的spinner下拉控件,原來是用一個背景圖片替換原生的spinner樣式,但是由于固定了寬度等,當(dāng)文字變多時,文字會被遮擋住,如何優(yōu)化樣式?
(2)如何讓spinner下拉選項的文字(默認(rèn)是靠左的),實現(xiàn)居中顯示?
答: 對于(1),(2)找了一圈,后來在stackoverflow上找到答案,spinner此時不用設(shè)置background為圖片,用定義的樣式xml文件實現(xiàn)。具體看代碼:
對于問題1:在spinner外包裹一個LinearLayout,為這個LinearLayout設(shè)置background
<LinearLayout
android:layout_width="200dp"
android:layout_height="40dp"
android:background="@drawable/bg_spinner"
>
<Spinner
android:id="@+id/print_spinner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
/>
</LinearLayout>
背景樣式文件,放在drawable文件下的bg_spinner.xml中
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="2dp">
<shape>
<corners android:radius="2dp"/>
<stroke
android:width="2dp"
android:color="#A4A4A4" />
<padding
android:top="2dp"
android:right="2dp"/>
</shape>
</item>
<item android:right="4dp">
<bitmap android:gravity="right|center_vertical"
android:src="@drawable/custom_spinner_icon"
>
</bitmap>
</item>
</layer-list>
注: 第一個item是設(shè)置spinner的圓角大小,邊框顏色粗細(xì)和padding,第二個item是設(shè)置旁邊的倒著的小三角箭頭
對于問題2,如何使spinner下拉選項Item中的文字居中?默認(rèn)是靠左顯示的。
第一步,設(shè)置一個xml文件命名為spinner_item.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:textColor="#929292"
android:textSize="22sp"
android:gravity="center"
android:textAlignment="center"
/>
注意:這里之前設(shè)置了屬性android:gravity="center",android:textAlignment="center,但是文字就是不居中,查閱了半天,后來發(fā)現(xiàn)原來設(shè)置android:layout_width和android:layout_height為wrap_content,改為match_parent后就生效了。
第二步,在java類中,調(diào)用spinner的時候,使用自定義的這個xml下拉
ArrayAdapter<String> adapter= new ArrayAdapter<String>(context, R.layout.spinner_item, myList);
adapter.setDropDownViewResource(R.layout.spinner_item)