前言
??我18年8月份寫過一篇文章RecycleView列表Item中包含EditText的爬坑筆記,百度搜索關(guān)鍵詞 RecycleView和EditText ,第一條結(jié)果就是這篇文章兴猩。如果小伙伴想解決日常開發(fā)中recycleView和EditText結(jié)合出現(xiàn)的那些坑浅缸,請移步上一篇那里卖漫。當然這篇文章同樣式以上一篇文章作為基礎(chǔ)的柑船,建議看完上一篇文章后澎怒,再讀這篇文章杭抠,能更好理解栗涂。
[圖片上傳中...(image.png-9239ed-1551319103954-0)]
??好了,廢話不多說祈争,進入正題斤程。如題目所言,日常開發(fā)中菩混,我遇到了多次列表式信息錄入的需求忿墅。大家可能不明白,列表式信息錄入具體啥意思沮峡,可以看下圖
需求1說明:
- 養(yǎng)殖行業(yè)下面的細目類疚脐,條數(shù)非固定,是服務(wù)端可配置邢疙;
- 中間是需要用戶輸入每條細目類對應的數(shù)量或者信息棍弄;
需求2說明:
- 設(shè)備信息下的設(shè)備條數(shù)是可以新增或者刪除的,總之一句話疟游,數(shù)量不固定呼畸;
- 同樣需要錄入對應的信息;
正文
??需求說明白了颁虐,看到需求的小伙伴蛮原,不知道你們有啥開發(fā)思路,反正我看到需求時候另绩,第一反應儒陨,是想用java代碼結(jié)合xml布局根據(jù)細目類數(shù)量動態(tài)添加布局的方式解決這個需求花嘶,但是細致想想,如果按照這種思路開發(fā)蹦漠,邏輯復雜程度不是一般椭员,可復用性太差,簡直是自虐笛园。再想到之前有recycleView和EditText結(jié)合的爬坑經(jīng)驗拆撼,最終決定繼續(xù)爬坑。喘沿。闸度。。蚜印。莺禁。
??選擇繼續(xù)爬坑,再細細構(gòu)思開發(fā)思路窄赋,這種開發(fā)方式哟冬,我想到可能最大的問題,就是如何拿到用戶錄入的信息忆绰。有句偉人說過:想到的都是問題浩峡,只有做起來,才能解決問題错敢。所以我就試著開始碼代碼了(開發(fā)思路其實沒啥翰灾,就不總結(jié)了,就是正常使用recycleView的基本思路稚茅,不懂的小伙伴請移步recycleView)纸淮。
- xml RecycleView文件部分(需求1和需求2在用一個頁面,沒毛病亚享,外層肯定使用scrollView 進行包裹,解決滑動沖突和數(shù)據(jù)顯示不全請移步雜記)
<RelativeLayout
android:descendantFocusability="beforeDescendants"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/mRecycleHangYe"
android:scrollbars="none"
android:overScrollMode="never"
android:layout_width="match_parent"
android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView>
</RelativeLayout>
需要說明就是android:descendantFocusability這個屬性咽块,外層包裹RelativeLayout/LinearLayout,并添加這個屬性android:descendantFocusability="blocksDescendants",是確保recycleView數(shù)量顯示完全欺税,但item中包含EditText,需要獲取焦點輸入內(nèi)容侈沪,所以改成android:descendantFocusability="beforeDescendants"否則EditText無法獲取焦點,無法輸入晚凿。
- xml Item文件部分
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="51dp">
<LinearLayout
android:id="@+id/ll"
android:background="@color/white"
android:paddingLeft="@dimen/margin_padding_15"
android:paddingRight="15dp"
android:layout_width="match_parent"
android:layout_height="@dimen/item_height">
<TextView
style="@style/applyCompanyBusinessInfo_Left"
android:id="@+id/mTv_num"
android:text="承保期限哈"/>
<EditText
android:inputType="number"
android:id="@+id/mEt_num"
android:layout_width="wrap_content"
android:layout_height="@dimen/item_height"
android:layout_weight="1"
android:background="@color/white"
android:drawablePadding="10dp"
android:gravity="center_vertical"
android:hint="請輸入資產(chǎn)信息"
android:paddingLeft="20dp"
android:paddingRight="10dp"
android:singleLine="true"
android:textColor="@color/gray3"
android:textColorHint="@color/gray9"
android:textSize="@dimen/font_normal" />
<TextView
android:id="@+id/mTv_danwei"
android:textColor="@color/gray3"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""/>
</LinearLayout>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_marginLeft="@dimen/padding"
android:background="@color/gray_e3"
android:layout_height="1dp"/>
</LinearLayout>
說明我開發(fā)最開始過程中亭罪,最外層部分高度*** android:layout_height="match_parent",結(jié)果運行調(diào)試發(fā)現(xiàn)晃虫,只顯示一條數(shù)據(jù)皆撩,打印日志數(shù)據(jù)源是多條數(shù)據(jù)沒問題扣墩,包裹嵌套數(shù)據(jù)顯示不全不問題也處理了哲银,只能是item部分問題扛吞,試著改成android:layout_height="51dp"***,問題解決了荆责,細節(jié)滥比!細節(jié)!細節(jié)哈做院。
*Java recycleView部分
mRecycleHangYe.setLayoutManager(new LinearLayoutManager(this));
if (hangYeAdapter == null) {
hangYeAdapter = new HangYeAdapter();
mRecycleHangYe.setAdapter(hangYeAdapter);
} else {
hangYeAdapter.notifyDataSetChanged();
}
Java Adapter部分
class HangYeAdapter extends RecyclerView.Adapter<HangYeAdapter.MyViewHolder> {
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(ApplyCompanyBusinessInfoActivity.this).
inflate(R.layout.item_apply_company_business_hangye, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Logger.d("*********************onBindViewHolder");
holder.setIsRecyclable(false);
if (position == hangYeInfosLists.size() - 1) {
holder.divider.setVisibility(View.GONE);
}
HangYeInfo b = hangYeInfosLists.get(position);
hangYeEditTextMap.put(b.getAssetName(), holder.mEtNum);
holder.mEtNum.setInputType(TextUtils.isEmpty(b.getAssetUnit()) ?
InputType.TYPE_CLASS_TEXT : InputType.TYPE_CLASS_NUMBER);
holder.mTvNum.setText(b.getAssetName());
holder.mTvDanwei.setText(b.getAssetUnit());
holder.mEtNum.setText(b.getNum());
}
@Override
public int getItemCount() {
return hangYeInfosLists.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.mTv_num)
TextView mTvNum;
@Bind(R.id.mEt_num)
EditText mEtNum;
@Bind(R.id.mTv_danwei)
TextView mTvDanwei;
@Bind(R.id.ll)
LinearLayout ll;
@Bind(R.id.divider)
View divider;
public MyViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
這里需要說明我這里拒絕了復用(數(shù)據(jù)量本身不大)holder.setIsRecyclable(false)盲泛,到這里,需求1的顯問題基本解決了键耕,就剩下了寺滚,如何獲取用戶輸入的信息這個問題了禽车,鑒于之前的爬坑經(jīng)驗崔步,我果斷使用map,解決問題
private Map<String, EditText> hangYeEditTextMap = new HashMap<>();
adapter中hangYeEditTextMap.put(b.getAssetName(), holder.mEtNum),存儲EditText,用的時候直接取出來:
String key = lists.get(i).getAssetName();
String inPutMsg = hangYeEditTextMap.get(key) != null ?
hangYeEditTextMap.get(key).getText().toString() : "0";
重點就這一句hangYeEditTextMap.get(key).getText().toString()盛正,其他都是邏輯問題酒奶,請忽略蚁孔。這樣真能獲取到用戶輸入的數(shù)據(jù),沒有出現(xiàn)對應錯亂的問題惋嚎。Nice杠氢,需求1問題解決!A砦椤鼻百!
??到這里,小伙伴是不是覺得摆尝,需求2同樣使用這種思路解決這個問題愕宋,如果有這種想法的小伙伴,你就too young, too simple, too naive需求2和需求1還是有區(qū)別的结榄,如下:
- 需求1列表頁面中贝,一旦數(shù)據(jù)遠固定,列表item數(shù)量就固定臼朗,而列表2列表item數(shù)量是可以編輯的邻寿;
- 需求1不涉及到刷新,需求2涉及到刷新數(shù)據(jù)视哑;
??所以需求2還是需要單獨解決的绣否,文章RecycleView列表Item中包含EditText的爬坑筆記成功避免刷新數(shù)據(jù),引起的無數(shù)坑挡毅,但是這里貌似不行蒜撮,所以只能硬著頭皮刷新。。段磨。實現(xiàn)思路如下:
- 用戶初次進入取逾,需要顯示一個備用Item,供用戶輸入增加Item使用,所以本地創(chuàng)建一個對象類苹支,包含用戶錄入的信息砾隅,同樣也是為了記錄用戶輸入的信息,并且在數(shù)據(jù)元增加一條空數(shù)據(jù):
class SheBeiBean{
String id;
String name;
String num;
String serial;
public SheBeiBean(String id, String name, String num, String bianhao) {
this.id = id;
this.name = name;
this.num = num;
this.serial = bianhao;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
public String getSerial() {
return serial;
}
public void setSerial(String serial) {
this.serial = serial;
}
}
private ArrayList<Object> sheBeiBeansLists = new ArrayList<>();
private void addSheBeiEmptyBean() {
sheBeiBeansLists.add(new SheBeiBean("", "", "", ""));
}
- 之后設(shè)置recycleView布局管理器和adapter(recycleView和item的布局就不貼出來债蜜,細節(jié)注意跟需求1一樣)
private void setSheBeiAdapter() {
if (sheBeiAdapter == null) {
sheBeiAdapter = new SheBeiAdapter();
mRecycleSheBei.setAdapter(sheBeiAdapter);
} else {
sheBeiAdapter.notifyDataSetChanged();
}
}
到這里不出意外晴埂,第一個編輯部分基本顯示出來了,剩下就是添加或者刪除新的編輯部分寻定,相信小伙伴們儒洛,肯定可以想到,操作數(shù)據(jù)源增加刪除就可以實現(xiàn)狼速,Nice,說得很對晶丘。
class SheBeiAdapter extends RecyclerView.Adapter<SheBeiAdapter.MyViewHolder> {
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(ApplyCompanyBusinessInfoActivity.this).
inflate(R.layout.item_apply_company_business_shebei, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.setIsRecyclable(false);
holder.mTv.setVisibility(position>0?View.INVISIBLE:View.VISIBLE);
holder.mTvDelete.setVisibility(sheBeiBeansLists.size()>1 ?View.VISIBLE:View.GONE);
holder.mTvAdd.setVisibility(position==sheBeiBeansLists.size()-1?
View.VISIBLE:View.GONE);
SheBeiBean b = (SheBeiBean) sheBeiBeansLists.get(position);
holder.mEtName.setText(b.getName());
holder.mEtNum.setText(b.getNum());
holder.mEtBiaohao.setText(b.getSerial());
holder.mEtNum.addTextChangedListener(new MyTextWatcher(MyTextWatcher.tagStr_SheBei,MyTextWatcher.TagView_num,position));
holder.mEtName.addTextChangedListener(new MyTextWatcher(MyTextWatcher.tagStr_SheBei,MyTextWatcher.TagView_name,position));
holder.mEtBiaohao.addTextChangedListener(new MyTextWatcher(MyTextWatcher.tagStr_SheBei,MyTextWatcher.TagView_serial,position));
holder.mTvDelete.setTag(position);
holder.mTvDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int index = (int) v.getTag();
sheBeiBeansLists.remove(index);
setSheBeiAdapter();
}
});
holder.mTvAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addSheBeiEmptyBean();
setSheBeiAdapter();
}
});
}
@Override
public int getItemCount() {
return sheBeiBeansLists.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.mTv)
TextView mTv;
@Bind(R.id.mTvDelete)
TextView mTvDelete;
@Bind(R.id.mEt_name)
EditText mEtName;
@Bind(R.id.mEt_num)
EditText mEtNum;
@Bind(R.id.mEt_biaohao)
EditText mEtBiaohao;
@Bind(R.id.mDivider1)
View mDivider1;
@Bind(R.id.mTvAdd)
TextView mTvAdd;
public MyViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
到這里,就又剩下關(guān)鍵問題了唐含,啥問題浅浮?當然是如何獲取用戶輸入的信息,如果按照需求1解決的方式解決問題捷枯,明顯不可能滚秩,關(guān)鍵問題就是需求2找不到EditText對應的獨一無二的關(guān)鍵key,而且涉及到增加刪除等問題,所以需求1解決思路基本放棄淮捆。
問題棘手就棘手在涉及到增加刪除郁油,每次增加刪除我們都是通過操作數(shù)據(jù)源(也可能是空的)實現(xiàn)的,另外 EditText獲取輸入的信息就兩種方式
- getText().ToString();
- holder.mEtNum.addTextChangedListener();
所以只能添加監(jiān)聽獲取輸入信息攀痊,再將信息實時的賦值到數(shù)據(jù)源中桐腌,代碼如下:
holder.mEtNum.addTextChangedListener(new MyTextWatcher(MyTextWatcher.tagStr_SheBei,MyTextWatcher.TagView_num,position));
holder.mEtName.addTextChangedListener(new MyTextWatcher(MyTextWatcher.tagStr_SheBei,MyTextWatcher.TagView_name,position));
holder.mEtBiaohao.addTextChangedListener(new MyTextWatcher(MyTextWatcher.tagStr_SheBei,MyTextWatcher.TagView_serial,position));
class MyTextWatcher implements TextWatcher {
public static final String TagView_name="name";
public static final String TagView_num="num";
public static final String TagView_serial="serial";
public static final String tagStr_SheBei="shebei";
public static final String tagStr_YuanCaiLiao="yuancailiao";
int position;
String viewType;
String infoType;
/**
*
* @param infoType 區(qū)分是設(shè)備還是原材料
* @param viewType 區(qū)分哪editText添加的監(jiān)聽
* @param position 用來獲取集合中需求操作的數(shù)據(jù)源
*/
public MyTextWatcher(String infoType,String viewType,int position) {
this.position = position;
this.viewType=viewType;
this.infoType=infoType;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
getUserInfoInfo(s.toString());
}
private void getUserInfoInfo(String inputStr){
switch (viewType){
case TagView_name:
if(tagStr_SheBei.equals(infoType)){
((SheBeiBean)sheBeiBeansLists.get(position)).setName(inputStr);
}else{
((YuanCaiLiaoBean)yuanCaiLiaoBeanList.get(position)).setName(inputStr);
}
break;
case TagView_num:
if(tagStr_SheBei.equals(infoType)){
((SheBeiBean)sheBeiBeansLists.get(position)).setNum(inputStr);
}else{
((YuanCaiLiaoBean)yuanCaiLiaoBeanList.get(position)).setNum(inputStr);
}
break;
case TagView_serial:
((SheBeiBean)sheBeiBeansLists.get(position)).setSerial(inputStr);
break;
}
}
}
這樣,數(shù)據(jù)就實時保存到數(shù)據(jù)源中了苟径,需要用戶輸入的信息的時候案站,直接去數(shù)據(jù)源中取可以了。到此大功告成棘街,希望能給小伙伴一丁點啟發(fā)蟆盐。文章到此結(jié)束,謝謝各位看官遭殉。
總結(jié)
開發(fā)思路都在文章里面石挂,想看總結(jié)的重新再看一遍文章哈。险污。痹愚。。。