最近天气真他娘的热,炸鸡啤酒,我觉得如果不演那么什么我从来都不看的韩剧,绝对没有人喜欢这种吃法。好了,废话不多说,天这么热,我只能晚上腾出时间来写这个东东,顺便引用吉日嘎拉的博客上面的一句话"每天进步一点点"。


OK,我们这次是要把这个界面翻成Android版,大家看过我的博客都知道我一直都是拿这几个界面再弄,

什么java实战篇也是用这个界面,唉,没办法,我只有这个界面。

先上一张Android版的图,吊胃口,下面的这张是模拟器上的图,怎么样,还像个app的样子吧。

首先我们来看一下.net webService端,在webService中我新增了一个方法

[WebMethod]publicCommonResponseUserInfoModify(UserInfoEntityuserInfoEntity){returnUserInfoBiz.GetInstance().ModifyUserInfo(userInfoEntity);}

接下里看一下Biz层

publicCommonResponseModifyUserInfo(UserInfoEntityuserInfoEntity){try{intsuc=UserInfoMngDAL.GetInstance().ModifyUserInfo(userInfoEntity);if(suc>0){returnnewCommonResponse(){IsSuccess=true};}returnnewCommonResponse(){IsSuccess=false,ErrorMessage=SaveFailed};}catch(Exceptionex){returnnewCommonResponse(){IsSuccess=false,ErrorMessage=ex.Message};}}

最后看一下DAL层

publicintModifyUserInfo(UserInfoEntityuserInfoEntity){using(BonusEntitiesbonusEntities=newBonusEntities()){if(bonusEntities.UerInfo.Any(u=>u.UseNo==userInfoEntity.UserNo))//hasexisted{UerInfouerInfoModify=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{UerInfouerInfo=newUerInfo();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);}returnbonusEntities.SaveChanges();}}

非常的简单,如果存在就是修改,否则是新建。在这里需要注意的是下面这句

uerInfo.Photo=Convert.FromBase64String()

这个解释的话先看一下我们的EF实体

我们的Photo是byte[]类型,因为Ksoap是无法传递byte[]的,所以在android客户端,我们要先将byte[]编码成string,然后在.net wenservice端再反编码。好了,这里就是webservice端。


接着就到了我们的android客户端了,他才是我们这篇文章的重头戏。先上一张真机上的图,开启笔记本wifi,手机连接wifi,更换代码中的IP,OK,运行

就是这张图,大家可能会问,那右边的那个东西是什么,是鸟的翅膀吗,不是,是一个人

这边的功能是如果用户勾选checkBox,则保存的时候会将图片一并提交webservice去做保存。


图也看了,那么先看一下页面布局

<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"><HorizontalScrollViewandroid:layout_height="wrap_content"android:layout_width="fill_parent"android:scrollbarAlwaysDrawHorizontalTrack="false"><TableLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/blue1"android:stretchColumns="0"><TableRow><TableLayoutandroid: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><TextViewandroid:text="@string/userName"android:gravity="right"android:textSize="8pt"></TextView><EditTextandroid: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><TextViewandroid:text="@string/userSex"android:layout_gravity="center_vertical"android:textSize="8pt"></TextView><Spinnerandroid:id="@+id/cmbUserSex"android:layout_width="fill_parent"android:layout_height="wrap_content"></Spinner></TableRow><TableRow><TextViewandroid:text="@string/userAge"android:gravity="right"android:textSize="8pt"></TextView><EditTextandroid:id="@+id/txtUserAge"android:editable="false"></EditText></TableRow><TableRow><TextViewandroid:text="@string/userBirthDay"android:gravity="right"android:textSize="8pt"android:layout_gravity="center_vertical"></TextView><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"><EditTextandroid: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><Buttonandroid: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><TextViewandroid:text="@string/userTemper"android:gravity="right"android:textSize="8pt"android:layout_gravity="center_vertical"></TextView><RadioGroupandroid:id="@+id/radioGroup"android:contentDescription="脾气"android:layout_width="wrap_content"android:orientation="horizontal"android:layout_height="wrap_content"><RadioButtonandroid: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><RadioButtonandroid: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><LinearLayoutandroid:orientation="horizontal"android:layout_height="wrap_content"android:layout_width="wrap_content"android:layout_span="2"><Buttonandroid: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><Buttonandroid: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><TableLayoutandroid:layout_width="wrap_content"android:background="@color/teal"android:layout_margin="1dp"android:layout_height="wrap_content"android:layout_column="1"><TableRow><ImageViewandroid: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><CheckBoxandroid:id="@+id/chkChoosePhoto"android:layout_marginLeft="10dp"android:layout_column="0"></CheckBox><Buttonandroid: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>


布局的话主要有以下几点,第一,这个布局总体采用TableLayout,因为我们的界面的宽度的缘故,所以我在table的外层加了个HorizontalScrollView,用来左右滚动。第二,这个界面的布局是采用左右各占一列, 在列中又嵌套了Table。做过Silverlight的人都知道,Grid布局是很好用的,这个和Silverlight的Grid布局有点像。布局的话其实都很简单,也没啥看点。


在界面中,大家都看到了有个下拉列表样子的东西,那是什么,是ComboBox?我靠,你以为这是在做Silverlight呢。这个是Android中的Spinner控件。我们来看一下他是如何加载下拉数据和响应事件的。

首先我们在string.xml文件中新增了一个string-array资源,用来加载到下拉列表。



在代码中,我们会构造一个Spinner加载数据的一个适配器,如下

privatevoidInitData(){//ArrayAdapter<String>adapter;//adapter=newArrayAdapter<String>(this,//android.R.layout.simple_spinner_item,sexArray);finalArrayAdapter<?>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(newOnItemSelectedListener(){//publicvoidonItemSelected(AdapterView<?>arg0,Viewarg1,//intarg2,longarg3){//StringselectedItem=adapter.getItem(arg2).toString();//}////publicvoidonNothingSelected(AdapterView<?>arg0){//}//});}

看到了吧,那句R.Array.SexArray就是从资源文件取出性别集合的。

setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

这句是表示我们的下拉列表展示简单的项(只有文子字),如果你想让你的下拉列表更生动,你可以去加载模版,比如在男选项前面放一个男人头像,女选项前面放一个女头像。这个其实和Silverlight的ComboBox的模版类似。OK,最后给Spinner设置适配器。我注释的上面部分是当不从资源文件加载数据的时候的代码,下面部分是下拉事件响应的代码。我们看一下下拉效果


此时,就可以在界面选择你想要的结果。

好了,那我们接下来看这个出生日期,为什么要先看出生日期呢,因为年龄是根据出生日期算出来的,难道您刚才没注意那个年龄的文本框是设置为不能编辑的吗(android:editable="false")。

出生日期后面的那个选择按钮完成的功能是弹出日期选择界面。看代码

this.btnChoose.setOnClickListener(newOnClickListener(){publicvoidonClick(Viewview){Calendarcalendar=Calendar.getInstance();DatePickerDialogdialog=newDatePickerDialog(owner,newDatePickerDialog.OnDateSetListener(){publicvoidonDateSet(DatePickerdp,intyear,intmonth,intdayOfMonth){txtBirthDay.setText(year+"-"+month+"-"+dayOfMonth);SimpleDateFormatdf=newSimpleDateFormat();df.applyPattern("yyyy-MM-ddhh:mm:ss");try{Datedt=df.parse(year+"-"+month+"-"+dayOfMonth+"00:00:01");intage=newDate().getYear()-dt.getYear();txtAge.setText(String.valueOf(age));}catch(ParseExceptione1){//TODOAuto-generatedcatchblocke1.printStackTrace();}}},calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),calendar.get(Calendar.DAY_OF_MONTH));dialog.show();}});


看到了吧,我们直接弹出android内置的Dialog(DatePickerDialog),看一下效果

在他的日期设置事件(onDateSet)中,我们拿到选择的日期,先赋给出生日期文本框,然后再用当前的年份减去选择的年份,算出来就是年龄,把年龄赋给年龄文本框。如果你想设置初始化的日期的话,需要注意他DatePickerDialog的构造函数最后三个参数,来自API的解释

OK,日期看完之后,就是右边的图片了,首先我们要知道图片从哪里来,当然是从手机里来,是个人都知道。我们看一下点击浏览按钮做的事情。

this.btnBrowser.setOnClickListener(newOnClickListener(){publicvoidonClick(Viewview){Intentintent=newIntent();intent.setType("image/*");intent.setAction(Intent.ACTION_GET_CONTENT);startActivityForResult(intent,1);}});

看到了吧,启动手机的图片照片搜索界面,如下

选择一张照片,图片就会显示到图片框中,如下

那么图片是怎么显示到图片框中的,第一步,我们要重写当前Activity的onActivityResult方法。

protectedvoidonActivityResult(intrequestCode,intresultCode,android.content.Intentdata){if(resultCode==RESULT_OK){Uriuri=data.getData();ContentResolvercontentResolver=this.getContentResolver();try{Bitmapbitmap=BitmapFactory.decodeStream(contentResolver.openInputStream(uri));imgUserPhoto.setImageBitmap(bitmap);}catch(FileNotFoundExceptione){}}super.onActivityResult(requestCode,resultCode,data);}

我们拿到图片的资源地址后,转化成Bitmap,赋给图片框。在这里图片框有多种显示拉伸方式,我就不多说了,自己查吧。OK,图片也显示完了,我们看最后的保存。


在看保存之前,我们先看一下取消

this.btnCancel.setOnClickListener(newOnClickListener(){publicvoidonClick(Viewview){finalAlertDialog.Builderbuilder=newAlertDialog.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);finalAlertDialogdialog=builder.create();dialog.show();dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){userinfomanage.this.setResult(RESULT_OK);userinfomanage.this.finish();}});}});

取消这个很简单,就是构造一个弹出框,点击确定关闭当前Activity,点击取消,不关闭界面

OK,最后我们看一下我们的save。

this.btnSave.setOnClickListener((newOnClickListener(){publicvoidonClick(Viewview){if(!CheckUserInput())return;UserInfoEntityuserInfoEntity=GetUserInfoEntity();SoapObjectsoapObject=ModifyUserInfoEntty(userInfoEntity);BooleanisSuccess=Boolean.valueOf(soapObject.getProperty("IsSuccess").toString());if(isSuccess){ShowMessage(R.string.SaveSuccess);}else{StringerrorMsg=soapObject.getProperty("ErrorMessage").toString();ShowMessage(errorMsg);}}}));

首先是check,如下,很简单

privateBooleanCheckUserInput(){StringuserName=this.txtUserName.getText().toString().trim();if(userName.length()==0){this.ShowMessage("姓名不能为空!");this.txtUserName.requestFocus();returnfalse;}StringbirthDay=this.txtBirthDay.getText().toString().trim();if(birthDay.length()==0){this.ShowMessage("出生日期不能为空!");this.btnBrowser.requestFocus();returnfalse;}returntrue;}

接着是拿到要保存的实体GetUserInfoEntity

privateUserInfoEntityGetUserInfoEntity(){UserInfoEntityuserInfoEntity=newUserInfoEntity();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()){StringstrByte=Base64.encode(GetImageByteArray());userInfoEntity.setProperty(6,strByte);}returnuserInfoEntity;}

需要注意的是这里Base64.encode(GetImageByteArray()),这个就是刚才说的KSoap不支持直接传byte[],而是要转码。GetImageByteArray这个方法是将图片框中的图片转化成byte[]。

privatebyte[]GetImageByteArray(){byte[]compressData=null;imgUserPhoto.setDrawingCacheEnabled(true);Bitmapbmp=Bitmap.createBitmap(imgUserPhoto.getDrawingCache());imgUserPhoto.setDrawingCacheEnabled(false);if(bmp!=null){compressData=GetByteArrayByBitmap(bmp);}returncompressData;}privatebyte[]GetByteArrayByBitmap(Bitmapbmp){byte[]compressData=null;ByteArrayOutputStreambyteOutputStream=newByteArrayOutputStream();bmp.compress(Bitmap.CompressFormat.JPEG,100,byteOutputStream);compressData=byteOutputStream.toByteArray();try{byteOutputStream.close();}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}returncompressData;}

这都是固定写法,不多做解释。OK,我们看一下实体的定义,免得看得人摸不着头脑

publicclassUserInfoEntityimplementsKvmSerializable{privateStringUserNo;privateStringUserName;privateStringUserSex;privateintUserAge;privateStringBirthDay;privateStringTemper;privateStringUserPhoto;@OverridepublicObjectgetProperty(intarg0){//TODOAuto-generatedmethodstubObjectproperty=null;switch(arg0){case0:property=this.UserNo;break;case1:property=this.UserName;break;case2:property=this.UserSex;break;case3:property=this.UserAge;break;case4:property=this.BirthDay;break;case5:property=this.Temper;break;case6:property=this.UserPhoto;break;default:break;}returnproperty;}@OverridepublicintgetPropertyCount(){//TODOAuto-generatedmethodstubreturn7;}@OverridepublicvoidgetPropertyInfo(intarg0,Hashtablearg1,PropertyInfoarg2){//TODOAuto-generatedmethodstubswitch(arg0){case0:arg2.type=PropertyInfo.STRING_CLASS;arg2.name="UserNo";break;case1:arg2.type=PropertyInfo.STRING_CLASS;arg2.name="UserName";break;case2:arg2.type=PropertyInfo.STRING_CLASS;arg2.name="UserSex";break;case3:arg2.type=PropertyInfo.INTEGER_CLASS;arg2.name="UserAge";break;case4:arg2.type=PropertyInfo.STRING_CLASS;arg2.name="BirthDay";break;case5:arg2.type=PropertyInfo.STRING_CLASS;arg2.name="Temper";break;case6:arg2.type=PropertyInfo.STRING_CLASS;arg2.name="UserPhoto";break;default:break;}}@OverridepublicvoidsetProperty(intarg0,Objectarg1){//TODOAuto-generatedmethodstubif(arg1==null)return;switch(arg0){case0:this.UserNo=arg1.toString();break;case1:this.UserName=arg1.toString();break;case2:this.UserSex=arg1.toString();break;case3:this.UserAge=Integer.parseInt(arg1.toString());break;case4:this.BirthDay=arg1.toString();break;case5:this.Temper=arg1.toString();break;case6:this.UserPhoto=arg1.toString();default:break;}}}

和.net WebServce端是对应的。OK,最后我们看一下保存(ModifyUserInfoEntty)的代码。

privateSoapObjectModifyUserInfoEntty(UserInfoEntityuserInfoEntity){SoapObjectrequest=newSoapObject(NAMESPACE,METHOD_NAME);PropertyInfopi=newPropertyInfo();pi.setName("userInfoEntity");pi.setValue(userInfoEntity);pi.setType(userInfoEntity.getClass());request.addProperty(pi);SoapSerializationEnvelopesoapEnvelope=newSoapSerializationEnvelope(SoapEnvelope.VER11);soapEnvelope.dotNet=true;HttpTransportSEhttpTS=newHttpTransportSE(URL);soapEnvelope.bodyOut=httpTS;soapEnvelope.setOutputSoapObject(request);//设置请求参数soapEnvelope.addMapping(NAMESPACE,"UserInfoEntity",userInfoEntity.getClass());newMarshalBase64().register(soapEnvelope);try{httpTS.call(SOAP_ACTION,soapEnvelope);}catch(IOExceptione){//TODOAuto-generatedcatchblockthis.ShowMessage(e.getMessage());//e.printStackTrace();}catch(XmlPullParserExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}SoapObjectresult=null;try{result=(SoapObject)soapEnvelope.getResponse();}catch(SoapFaulte){//TODOAuto-generatedcatchblocke.printStackTrace();}returnresult;}

这里需要注意的是new MarshalBase64().register(soapEnvelope);这是要告诉soap 信使message中包含有Base64转过的byte[]。OK,最后,我们鼓起勇气点击save。

走起,见证奇迹的时刻

yeah,成功了,图片是否成功我们需要借助C#版的程序看一下,成功了。

最后,哥们这博客可真是货真价实,中兴U880S测试机。

评价一下你不会吃亏,评价一下你不会上当,你评的越多,我写的越多。他大舅他二舅都是他舅,高桌子低板凳都是木头,进来的都是干这一行的,给个评价吧。

更多相关文章

  1. Android多点触控技术实战,自由地对图片进行缩放和移动
  2. 关于android中的.9图(一)——如何画.9图
  3. 浅谈android中图片处理之图形变换特效Matrix(四)
  4. 关于 android app 返回键模拟 home键 功能的介绍_仿QQ返回键 又
  5. Android(安卓)UI开发第二十九篇——Android中五种常用的menu(菜单
  6. Android(安卓)拼接两个图片
  7. Android拼图游戏开发全纪录0
  8. Android(安卓)OpenGLES2.0(九)——利用OpenGL进行图片处理
  9. Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Dr

随机推荐

  1. Android 下枚举型使用、及与 int 转换的
  2. Weex 初体验(2)-navigator android跳转
  3. 修改linux/Android启动logo
  4. android6.0、7.0、8.0新特性总结之开发应
  5. Windows环境下编译Assimp库生成Android可
  6. Android无障碍浅析
  7. Android 常用图片框架对比
  8. android与js的交互之jsbridge使用
  9. Android之玩转View(六):Canvas基础使用和Reg
  10. android版本飞鸽传书源码