您好,登錄后才能下訂單哦!
最近天氣真他娘的熱,炸雞啤酒,我覺(jué)得如果不演那么什么我從來(lái)都不看的韓劇,絕對(duì)沒(méi)有人喜歡這種吃法。好了,廢話(huà)不多說(shuō),天這么熱,我只能晚上騰出時(shí)間來(lái)寫(xiě)這個(gè)東東,順便引用吉日嘎拉的博客上面的一句話(huà)"每天進(jìn)步一點(diǎn)點(diǎn)"。
OK,我們這次是要把這個(gè)界面翻成Android版,大家看過(guò)我的博客都知道我一直都是拿這幾個(gè)界面再弄,
什么java實(shí)戰(zhàn)篇也是用這個(gè)界面,唉,沒(méi)辦法,我只有這個(gè)界面。
先上一張Android版的圖,吊胃口,下面的這張是模擬器上的圖,怎么樣,還像個(gè)app的樣子吧。
首先我們來(lái)看一下.net webService端,在webService中我新增了一個(gè)方法
[WebMethod] public CommonResponse UserInfoModify(UserInfoEntity userInfoEntity) { return UserInfoBiz.GetInstance().ModifyUserInfo(userInfoEntity); }
接下里看一下Biz層
public CommonResponse ModifyUserInfo(UserInfoEntity userInfoEntity) { try { int suc = UserInfoMngDAL.GetInstance().ModifyUserInfo(userInfoEntity); if (suc > 0) { return new CommonResponse() { IsSuccess = true }; } return new CommonResponse() { IsSuccess = false, ErrorMessage = SaveFailed }; } catch (Exception ex) { return new CommonResponse() { IsSuccess = false, ErrorMessage = ex.Message }; } }
最后看一下DAL層
public int ModifyUserInfo(UserInfoEntity userInfoEntity) { using (BonusEntities bonusEntities = new BonusEntities()) { if (bonusEntities.UerInfo.Any(u => u.UseNo == userInfoEntity.UserNo)) //has existed { UerInfo uerInfoModify = bonusEntities.UerInfo.SingleOrDefault(u => u.UseNo == userInfoEntity.UserNo); uerInfoModify.Name = userInfoEntity.UserName; uerInfoModify.Sex = userInfoEntity.UserSex == "男" ? "1" : "2"; uerInfoModify.Age = userInfoEntity.UserAge; uerInfoModify.Temper = userInfoEntity.Temper; uerInfoModify.BirthDay = DateTime.Parse(string.Concat(userInfoEntity.BirthDay, " 00:00:01")); if (!string.IsNullOrWhiteSpace(userInfoEntity.UserPhoto)) { uerInfoModify.Photo = Convert.FromBase64String(userInfoEntity.UserPhoto); } } else { UerInfo uerInfo = new UerInfo(); uerInfo.UseNo = userInfoEntity.UserNo; uerInfo.Name = userInfoEntity.UserName; uerInfo.Sex = userInfoEntity.UserSex == "男" ? "1" : "2"; uerInfo.Age = userInfoEntity.UserAge; uerInfo.Temper = userInfoEntity.Temper; uerInfo.BirthDay = DateTime.Parse(string.Concat(userInfoEntity.BirthDay, " 00:00:01")); if (!string.IsNullOrWhiteSpace(userInfoEntity.UserPhoto)) { uerInfo.Photo = Convert.FromBase64String(userInfoEntity.UserPhoto); } bonusEntities.UerInfo.Add(uerInfo); } return bonusEntities.SaveChanges(); } }
非常的簡(jiǎn)單,如果存在就是修改,否則是新建。在這里需要注意的是下面這句
uerInfo.Photo = Convert.FromBase64String()
這個(gè)解釋的話(huà)先看一下我們的EF實(shí)體
我們的Photo是byte[]類(lèi)型,因?yàn)镵soap是無(wú)法傳遞byte[]的,所以在android客戶(hù)端,我們要先將byte[]編碼成string,然后在.net wenservice端再反編碼。好了,這里就是webservice端。
接著就到了我們的android客戶(hù)端了,他才是我們這篇文章的重頭戲。先上一張真機(jī)上的圖,開(kāi)啟筆記本wifi,手機(jī)連接wifi,更換代碼中的IP,OK,運(yùn)行
就是這張圖,大家可能會(huì)問(wèn),那右邊的那個(gè)東西是什么,是鳥(niǎo)的翅膀嗎,不是,是一個(gè)人
這邊的功能是如果用戶(hù)勾選checkBox,則保存的時(shí)候會(huì)將圖片一并提交webservice去做保存。
圖也看了,那么先看一下頁(yè)面布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <HorizontalScrollView android:layout_height="wrap_content" android:layout_width="fill_parent" android:scrollbarAlwaysDrawHorizontalTrack="false"> <TableLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/blue1" android:stretchColumns="0"> <TableRow> <TableLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:stretchColumns="1" android:padding="3dp" android:layout_column="0" android:layout_margin="1dp" android:background="@color/teal"> <TableRow> <TextView android:text="@string/userName" android:gravity="right" android:textSize="8pt"></TextView> <EditText android:id="@+id/txtUserName" android:drawableLeft="@drawable/userhint" android:hint="@string/hintInputUserName" android:textColorHint="@color/hintColor" android:width="200dp" android:singleLine="true" android:maxLength="25"></EditText> </TableRow> <TableRow> <TextView android:text="@string/userSex" android:layout_gravity="center_vertical" android:textSize="8pt"> </TextView> <Spinner android:id="@+id/cmbUserSex" android:layout_width="fill_parent" android:layout_height="wrap_content"></Spinner> </TableRow> <TableRow> <TextView android:text="@string/userAge" android:gravity="right" android:textSize="8pt"></TextView> <EditText android:id="@+id/txtUserAge" android:editable="false"></EditText> </TableRow> <TableRow> <TextView android:text="@string/userBirthDay" android:gravity="right" android:textSize="8pt" android:layout_gravity="center_vertical"></TextView> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <EditText android:id="@+id/txtUserBirthDay" android:editable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:width="140dp" android:hint="@string/hintChooseBirth" android:textColorHint="@color/hintColor" android:drawableLeft="@drawable/calander" android:singleLine="true"></EditText> <Button android:id="@+id/btnChoose" android:layout_width="80dp" android:layout_height="45dp" android:drawableLeft="@drawable/pencil" android:layout_gravity="center_vertical" android:text="@string/btnChoose" android:textStyle="bold"></Button> </LinearLayout> </TableRow> <TableRow> <TextView android:text="@string/userTemper" android:gravity="right" android:textSize="8pt" android:layout_gravity="center_vertical"></TextView> <RadioGroup android:id="@+id/radioGroup" android:contentDescription="脾氣" android:layout_width="wrap_content" android:orientation="horizontal" android:layout_height="wrap_content"> <RadioButton android:layout_width="wrap_content" android:textColor="@color/red1" android:layout_height="wrap_content" android:id="@+id/radioTemper1" android:text="@string/userTemper1" android:checked="true"></RadioButton> <RadioButton android:layout_width="wrap_content" android:textColor="@color/red1" android:layout_height="wrap_content" android:id="@+id/radioTemper2" android:text="@string/userTemper2"></RadioButton> </RadioGroup> </TableRow> <TableRow> <LinearLayout android:orientation="horizontal" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_span="2"> <Button android:id="@+id/btnSave" android:text="@string/btnSave" android:textColor="@color/blue" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:textStyle="bold"></Button> <Button android:text="@string/btnCancelText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:id="@+id/btnCancel" android:textColor="@color/blue" android:textStyle="bold" ></Button> </LinearLayout> </TableRow> </TableLayout> <TableLayout android:layout_width="wrap_content" android:background="@color/teal" android:layout_margin="1dp" android:layout_height="wrap_content" android:layout_column="1"> <TableRow> <ImageView android:id="@+id/imgUserPhoto" android:background="@color/imgBg" android:layout_marginLeft="10dp" android:layout_marginTop="5dp" android:layout_marginRight="5dp" android:layout_width="160dp" android:layout_height="240dp" android:src="@drawable/deaultphoto" android:scaleType="fitCenter" android:layout_span="2" /> </TableRow> <TableRow> <CheckBox android:id="@+id/chkChoosePhoto" android:layout_marginLeft="10dp" android:layout_column="0"></CheckBox> <Button android:id="@+id/btnBrowser" android:text="@string/btnChoosePhoto" android:textStyle="bold" android:layout_width="150dp" android:layout_height="45dp" android:layout_marginTop="1dp" android:textColor="@color/blue" android:layout_column="1"></Button> </TableRow> </TableLayout> </TableRow> </TableLayout> </HorizontalScrollView> </LinearLayout>
布局的話(huà)主要有以下幾點(diǎn),第一,這個(gè)布局總體采用TableLayout,因?yàn)槲覀兊慕缑娴膶挾鹊木壒?,所以我在table的外層加了個(gè)HorizontalScrollView,用來(lái)左右滾動(dòng)。第二,這個(gè)界面的布局是采用左右各占一列, 在列中又嵌套了Table。做過(guò)Silverlight的人都知道,Grid布局是很好用的,這個(gè)和Silverlight的Grid布局有點(diǎn)像。布局的話(huà)其實(shí)都很簡(jiǎn)單,也沒(méi)啥看點(diǎn)。
在界面中,大家都看到了有個(gè)下拉列表樣子的東西,那是什么,是ComboBox?我靠,你以為這是在做Silverlight呢。這個(gè)是Android中的Spinner控件。我們來(lái)看一下他是如何加載下拉數(shù)據(jù)和響應(yīng)事件的。
首先我們?cè)趕tring.xml文件中新增了一個(gè)string-array資源,用來(lái)加載到下拉列表。
在代碼中,我們會(huì)構(gòu)造一個(gè)Spinner加載數(shù)據(jù)的一個(gè)適配器,如下
private void InitData() { // ArrayAdapter<String> adapter; // adapter = new ArrayAdapter<String>(this, // android.R.layout.simple_spinner_item, sexArray); final ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(this, R.array.sexArray, android.R.layout.simple_spinner_item); adapter .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spnUserSex.setAdapter(adapter); // spnUserSex.setOnItemSelectedListener(new OnItemSelectedListener() { // public void onItemSelected(AdapterView<?> arg0, View arg1, // int arg2, long arg3) { // String selectedItem = adapter.getItem(arg2).toString(); // } // // public void onNothingSelected(AdapterView<?> arg0) { // } // }); }
看到了吧,那句R.Array.SexArray就是從資源文件取出性別集合的。
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
這句是表示我們的下拉列表展示簡(jiǎn)單的項(xiàng)(只有文子字),如果你想讓你的下拉列表更生動(dòng),你可以去加載模版,比如在男選項(xiàng)前面放一個(gè)男人頭像,女選項(xiàng)前面放一個(gè)女頭像。這個(gè)其實(shí)和Silverlight的ComboBox的模版類(lèi)似。OK,最后給Spinner設(shè)置適配器。我注釋的上面部分是當(dāng)不從資源文件加載數(shù)據(jù)的時(shí)候的代碼,下面部分是下拉事件響應(yīng)的代碼。我們看一下下拉效果
此時(shí),就可以在界面選擇你想要的結(jié)果。
好了,那我們接下來(lái)看這個(gè)出生日期,為什么要先看出生日期呢,因?yàn)槟挲g是根據(jù)出生日期算出來(lái)的,難道您剛才沒(méi)注意那個(gè)年齡的文本框是設(shè)置為不能編輯的嗎(android:editable="false")。
出生日期后面的那個(gè)選擇按鈕完成的功能是彈出日期選擇界面。看代碼
this.btnChoose.setOnClickListener(new OnClickListener() { public void onClick(View view) { Calendar calendar = Calendar.getInstance(); DatePickerDialog dialog = new DatePickerDialog(owner, new DatePickerDialog.OnDateSetListener() { public void onDateSet(DatePicker dp, int year, int month, int dayOfMonth) { txtBirthDay.setText(year + "-" + month + "-" + dayOfMonth); SimpleDateFormat df = new SimpleDateFormat(); df.applyPattern("yyyy-MM-dd hh:mm:ss"); try { Date dt = df.parse(year + "-" + month + "-" + dayOfMonth + " 00:00:01"); int age = new Date().getYear() - dt.getYear(); txtAge.setText(String.valueOf(age)); } catch (ParseException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } }, calendar.get(Calendar.YEAR), calendar .get(Calendar.MONTH), calendar .get(Calendar.DAY_OF_MONTH)); dialog.show(); } });
看到了吧,我們直接彈出android內(nèi)置的Dialog(DatePickerDialog),看一下效果
在他的日期設(shè)置事件(onDateSet)中,我們拿到選擇的日期,先賦給出生日期文本框,然后再用當(dāng)前的年份減去選擇的年份,算出來(lái)就是年齡,把年齡賦給年齡文本框。如果你想設(shè)置初始化的日期的話(huà),需要注意他DatePickerDialog的構(gòu)造函數(shù)最后三個(gè)參數(shù),來(lái)自API的解釋
OK,日期看完之后,就是右邊的圖片了,首先我們要知道圖片從哪里來(lái),當(dāng)然是從手機(jī)里來(lái),是個(gè)人都知道。我們看一下點(diǎn)擊瀏覽按鈕做的事情。
this.btnBrowser.setOnClickListener(new OnClickListener() { public void onClick(View view) { Intent intent = new Intent(); intent.setType("p_w_picpath/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(intent, 1); } });
看到了吧,啟動(dòng)手機(jī)的圖片照片搜索界面,如下
選擇一張照片,圖片就會(huì)顯示到圖片框中,如下
那么圖片是怎么顯示到圖片框中的,第一步,我們要重寫(xiě)當(dāng)前Activity的onActivityResult方法。
protected void onActivityResult(int requestCode, int resultCode, android.content.Intent data) { if (resultCode == RESULT_OK) { Uri uri = data.getData(); ContentResolver contentResolver = this.getContentResolver(); try { Bitmap bitmap = BitmapFactory.decodeStream(contentResolver .openInputStream(uri)); imgUserPhoto.setImageBitmap(bitmap); } catch (FileNotFoundException e) { } } super.onActivityResult(requestCode, resultCode, data); }
我們拿到圖片的資源地址后,轉(zhuǎn)化成Bitmap,賦給圖片框。在這里圖片框有多種顯示拉伸方式,我就不多說(shuō)了,自己查吧。OK,圖片也顯示完了,我們看最后的保存。
在看保存之前,我們先看一下取消
this.btnCancel.setOnClickListener(new OnClickListener() { public void onClick(View view) { final AlertDialog.Builder builder = new AlertDialog.Builder( owner); builder.setIcon(R.drawable.info); builder.setTitle(R.string.titleSystemCodeModifyName); builder.setMessage("您確定要退出修改嗎?"); builder.setPositiveButton(R.string.btnSure, null); builder.setNegativeButton(R.string.btnCancelText, null); final AlertDialog dialog = builder.create(); dialog.show(); dialog.getButton(AlertDialog.BUTTON_POSITIVE) .setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { userinfomanage.this.setResult(RESULT_OK); userinfomanage.this.finish(); } }); } });
取消這個(gè)很簡(jiǎn)單,就是構(gòu)造一個(gè)彈出框,點(diǎn)擊確定關(guān)閉當(dāng)前Activity,點(diǎn)擊取消,不關(guān)閉界面
OK,最后我們看一下我們的save。
this.btnSave.setOnClickListener((new OnClickListener() { public void onClick(View view) { if (!CheckUserInput()) return; UserInfoEntity userInfoEntity = GetUserInfoEntity(); SoapObject soapObject = ModifyUserInfoEntty(userInfoEntity); Boolean isSuccess = Boolean.valueOf(soapObject.getProperty( "IsSuccess").toString()); if (isSuccess) { ShowMessage(R.string.SaveSuccess); } else { String errorMsg = soapObject.getProperty("ErrorMessage") .toString(); ShowMessage(errorMsg); } } }));
首先是check,如下,很簡(jiǎn)單
private Boolean CheckUserInput() { String userName = this.txtUserName.getText().toString().trim(); if (userName.length() == 0) { this.ShowMessage("姓名不能為空!"); this.txtUserName.requestFocus(); return false; } String birthDay = this.txtBirthDay.getText().toString().trim(); if (birthDay.length() == 0) { this.ShowMessage("出生日期不能為空!"); this.btnBrowser.requestFocus(); return false; } return true; }
接著是拿到要保存的實(shí)體GetUserInfoEntity
private UserInfoEntity GetUserInfoEntity() { UserInfoEntity userInfoEntity = new UserInfoEntity(); userInfoEntity.setProperty(1, txtUserName.getText().toString()); userInfoEntity.setProperty(0, userNo); userInfoEntity.setProperty(2, spnUserSex.getSelectedItem()); userInfoEntity.setProperty(3, txtAge.getText()); userInfoEntity.setProperty(4, txtBirthDay.getText()); userInfoEntity.setProperty(5, radiobtnTemper1.isChecked() ? "1" : "2"); if (chkPhoto.isChecked()) { String strByte = Base64.encode(GetImageByteArray()); userInfoEntity.setProperty(6, strByte); } return userInfoEntity; }
需要注意的是這里Base64.encode(GetImageByteArray()),這個(gè)就是剛才說(shuō)的KSoap不支持直接傳byte[],而是要轉(zhuǎn)碼。GetImageByteArray這個(gè)方法是將圖片框中的圖片轉(zhuǎn)化成byte[]。
private byte[] GetImageByteArray() { byte[] compressData = null; imgUserPhoto.setDrawingCacheEnabled(true); Bitmap bmp = Bitmap.createBitmap(imgUserPhoto.getDrawingCache()); imgUserPhoto.setDrawingCacheEnabled(false); if (bmp != null) { compressData = GetByteArrayByBitmap(bmp); } return compressData; } private byte[] GetByteArrayByBitmap(Bitmap bmp) { byte[] compressData = null; ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.JPEG, 100, byteOutputStream); compressData = byteOutputStream.toByteArray(); try { byteOutputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return compressData; }
這都是固定寫(xiě)法,不多做解釋。OK,我們看一下實(shí)體的定義,免得看得人摸不著頭腦
public class UserInfoEntity implements KvmSerializable { private String UserNo; private String UserName; private String UserSex; private int UserAge; private String BirthDay; private String Temper; private String UserPhoto; @Override public Object getProperty(int arg0) { // TODO Auto-generated method stub Object property = null; switch (arg0) { case 0: property = this.UserNo; break; case 1: property = this.UserName; break; case 2: property = this.UserSex; break; case 3: property = this.UserAge; break; case 4: property = this.BirthDay; break; case 5: property = this.Temper; break; case 6: property = this.UserPhoto; break; default: break; } return property; } @Override public int getPropertyCount() { // TODO Auto-generated method stub return 7; } @Override public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo arg2) { // TODO Auto-generated method stub switch (arg0) { case 0: arg2.type = PropertyInfo.STRING_CLASS; arg2.name = "UserNo"; break; case 1: arg2.type = PropertyInfo.STRING_CLASS; arg2.name = "UserName"; break; case 2: arg2.type = PropertyInfo.STRING_CLASS; arg2.name = "UserSex"; break; case 3: arg2.type = PropertyInfo.INTEGER_CLASS; arg2.name = "UserAge"; break; case 4: arg2.type = PropertyInfo.STRING_CLASS; arg2.name = "BirthDay"; break; case 5: arg2.type = PropertyInfo.STRING_CLASS; arg2.name = "Temper"; break; case 6: arg2.type = PropertyInfo.STRING_CLASS; arg2.name = "UserPhoto"; break; default: break; } } @Override public void setProperty(int arg0, Object arg1) { // TODO Auto-generated method stub if (arg1 == null) return; switch (arg0) { case 0: this.UserNo = arg1.toString(); break; case 1: this.UserName = arg1.toString(); break; case 2: this.UserSex = arg1.toString(); break; case 3: this.UserAge = Integer.parseInt(arg1.toString()); break; case 4: this.BirthDay = arg1.toString(); break; case 5: this.Temper = arg1.toString(); break; case 6: this.UserPhoto = arg1.toString(); default: break; } } }
和.net WebServce端是對(duì)應(yīng)的。OK,最后我們看一下保存(ModifyUserInfoEntty)的代碼。
private SoapObject ModifyUserInfoEntty(UserInfoEntity userInfoEntity) { SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); PropertyInfo pi = new PropertyInfo(); pi.setName("userInfoEntity"); pi.setValue(userInfoEntity); pi.setType(userInfoEntity.getClass()); request.addProperty(pi); SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope( SoapEnvelope.VER11); soapEnvelope.dotNet = true; HttpTransportSE httpTS = new HttpTransportSE(URL); soapEnvelope.bodyOut = httpTS; soapEnvelope.setOutputSoapObject(request);// 設(shè)置請(qǐng)求參數(shù) soapEnvelope.addMapping(NAMESPACE, "UserInfoEntity", userInfoEntity .getClass()); new MarshalBase64().register(soapEnvelope); try { httpTS.call(SOAP_ACTION, soapEnvelope); } catch (IOException e) { // TODO Auto-generated catch block this.ShowMessage(e.getMessage()); // e.printStackTrace(); } catch (XmlPullParserException e) { // TODO Auto-generated catch block e.printStackTrace(); } SoapObject result = null; try { result = (SoapObject) soapEnvelope.getResponse(); } catch (SoapFault e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; }
這里需要注意的是new MarshalBase64().register(soapEnvelope);這是要告訴soap 信使message中包含有Base64轉(zhuǎn)過(guò)的byte[]。OK,最后,我們鼓起勇氣點(diǎn)擊save。
走起,見(jiàn)證奇跡的時(shí)刻
yeah,成功了,圖片是否成功我們需要借助C#版的程序看一下,成功了。
最后,哥們這博客可真是貨真價(jià)實(shí),中興U880S測(cè)試機(jī)。
評(píng)價(jià)一下你不會(huì)吃虧,評(píng)價(jià)一下你不會(huì)上當(dāng),你評(píng)的越多,我寫(xiě)的越多。他大舅他二舅都是他舅,高桌子低板凳都是木頭,進(jìn)來(lái)的都是干這一行的,給個(gè)評(píng)價(jià)吧。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。