当前位置:  编程技术>移动开发
本页文章导读:
    ▪存档自定义对象        归档自定义对象Cocoa中,归档数据到文件,使用NSKeyedArchiver的archiveRootObject:toFile:方法。对于一般的数据类型(例如字符串),这个步骤是非常简单的。Apple官方文档中,这些数据类型包括: .........
    ▪ popupwindow 中 EditText与 软键盘 的有关问题与探索        popupwindow 中 EditText与 软键盘 的问题与探索遇到一个问题, 情况是这样的: 一个Activity,上面只有一个录音按钮。 一个popupWindow,点击录音按钮,发出命令,弹出popupwindow。 popwindow里面有一.........
    ▪ GridView实现一起显示并左右滚动       GridView实现一行显示并左右滚动 [java] view plaincopy public class GridViewDemo extends Activity {       @Override       public void onCreate(Bundle savedInstanceState) {           super.onCreate(save.........

[1]存档自定义对象
    来源: 互联网  发布时间: 2014-02-18
归档自定义对象

Cocoa中,归档数据到文件,使用NSKeyedArchiver的archiveRootObject:toFile:方法。对于一般的数据类型(例如字符串),这个步骤是非常简单的。Apple官方文档中,这些数据类型包括:

    NSData

    NSString

    NSNumber

    NSDate

    NSArray

    NSDictionary

很显然,复杂数据例如UIImage,无法直接归档。但我们有一种变通的做法,先将UIImage对象转换为NSData,再对NSData进行归档。1

注1:准确地说,这依赖于iOS的版本。在iOS4中,UIImage未实现NSCoding协议,在iOS5中,UIImage实现了NSCoding协议。

对于自定义的类型,我们也可以参考这一做法,即先将将自定义类型转换为NSData,再对NSData进行归档。

问题在于,NSKeyedArchiver在归档一个自定义对象时,怎么知道如何将一个自定义对象编码为一个NSData?而且,当我们从文件中反归档时,NSKeyedUnarchiver怎么知道将NSData转变为一个自定义对象?

这就是NSCoding 协议需要解决的问题。实际上,NSCoding协议规定的两个方法,分别用于解决这两个问题。

当NSKeyedArchiver 在归档一个对象时,将调用对象的encodeWithCoder:方法,用于将对象转换为NSData(或NSString等其他5种类型);而NSKeyedUnarchiver在反归档一个对象时,则调用对象的initWithCoder:方法,用于将NSData(或NSString等其他5种类型)转换为指定的对象类型。

上述6种类型(NSData、NSString等)在归档/反归档时显得尤其简单,是因为苹果已经为我们实现了NSCoding协议。

而自定义对象不同,需要程序员自己实现其NSCoding协议。

新建项目,创建一个类MyClass,在头文件中声明对NSCoding协议的实现。

然后为他设计属性如下:

@interface MyClass : NSObject<NSCoding>

@property(strong,nonatomic)NSString* name;

@property(assign,nonatomic)int age;

@property(assign,nonatomic)BOOL sex;

@end

然后,在实现中实现NSCoding协议:

@implementation MyClass

@synthesize name,age,sex;

-(void)encodeWithCoder:(NSCoder *)encoder{

    [encoderencodeObject:self.name forKey:@"name"];

    [encoderencodeObject:[NSNumber numberWithInt: self.age] forKey:@"age"];

    [encoderencodeObject:[NSNumber numberWithBool: self.sex] forKey:@"sex"];

}

- (id)initWithCoder:(NSCoder *)decoder {

    if (self = [superinit]) {

       self.name = [decoder decodeObjectForKey:@"name"];

       self.age =((NSNumber*)[decoderdecodeObjectForKey:@"age"]).intValue;

       self.sex =((NSNumber*) [decoderdecodeObjectForKey:@"sex"]).boolValue;

    }

    return self;  

}

@end

在encodeWithCoder:方法中,这两句好像显得有点多余:

[encoder encodeObject:[NSNumber numberWithInt: self.age]forKey:@"age"];

[encoder encodeObject:[NSNumber numberWithBool: self.sex]forKey:@"sex"];

然而事实并不是这样的,encoder对象只能对已经实现了NSCoding的对象进行编码(即转换为6种类型之一),对于int、BOOL这样的简单类型则不行。因此,我们需要对age和sex属性转换为其他类型(6种类型之一),比如NSNumber。

同样,在initWithCoder:方法中,我们必须对decoder反编码后的数据进行必要的转换,将它们由NSNumber(因为编码时我们是用NSNumber存储的)转换为相应属性原来的类型,才能进行赋值:

self.age =((NSNumber*)[decoderdecodeObjectForKey:@"age"]).intValue;

self.sex =((NSNumber*) [decoder decodeObjectForKey:@"sex"]).boolValue;

接下来,我们使用NSKeyedArchiver/NSKeyedUnarchiver来对MyClass进行归档/反归档。

打开ViewController.xib,设计如下UI界面:


使用Asistant Editor,创建必要的连接。这时ViewController.h文件内容将显示如下:

#import "MyClass.h"

#define AppDocuments [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0]

@interface ViewController : UIViewController<UITextFieldDelegate>

@property (retain, nonatomic) IBOutlet UITextField *tfName;

@property (retain, nonatomic) IBOutlet UITextField *tfAge;

@property (retain, nonatomic) IBOutlet UISegmentedControl *segSex;

@property (retain, nonatomic) IBOutlet UIButton *button;

- (IBAction)archiveUnarchive:(id)sender;

@end

在ViewDidLoad方法中,加入语句

[self initUI:nil];

其中,initUI:方法定义如下:

-(void)initUI:(MyClass*)obj{

    if (obj==nil) {

       tfName.text=nil;

       tfAge.text=nil;

       segSex.selectedSegmentIndex=0;

}else{

       tfName.text=obj.name;

       tfAge.text=[NSString stringWithFormat:@"%d",obj.age];

       segSex.selectedSegmentIndex=obj.sex;

}

}

定义方法makeMyClassInstance,在这个方法中我们通过用户在界面是输入的内容创建MyClass实例:

-(MyClass*)makeMyClassInstance{

    MyClass*obj=[[MyClass alloc]init];

   obj.name=tfName.text;

    obj.age=[tfAge.textintValue];

    obj.sex=[segSexselectedSegmentIndex]!=0;

    return [objautorelease];

}

定义按钮事件的Action方法如下:

- (IBAction)archiveUnarchive:(id)sender {

   button.enabled=NO;

    NSString*filePath=[AppDocuments stringByAppendingPathComponent:@"customobject.txt"];

    if(button.tag==0) {

       if (tfName && tfName.text.length>0 && tfAge&& tfAge.text.length>0) {

           button.tag=1;

           [button setTitle:@"反归档" forState:UIControlStateNormal];

           MyClass* obj=[self makeMyClassInstance];

           [NSKeyedArchiver archiveRootObject:obj toFile:filePath];

           [self initUI:nil];

       }

       

    }else{

       button.tag=0;

       [button setTitle:@"归档" forState:UIControlStateNormal];

       MyClass* obj=[NSKeyedUnarchiver unarchiveObjectWithFile:filePath];

       [self initUI:obj];

    }

   button.enabled=YES;

}

运行程序,在界面中输入一些信息,然后点击“归档”按钮。

归档后,用户输入将再次清空,“归档”按钮将显示为“反归档”。在应用程序的documents目录,我们将找到归档文件customeobject.txt。

回到程序,点击“反归档”按钮,将再次从customobject.txt文件中获取MyClass对象,并将对象属性读取到UI控件中。

除了直接将MyClass对象作为RootObject(根对象)归档到文件以外,更通常的做法是将MyClass对象放入集合(Array或Dictionary),再对集合对象进行归档。

此外,MyClass可以递归,即它的属性可以是另一个MyClass对象并且这个属性也可以被归档和反归档。

我们可以在MyClass中增加属性parent,然后在encodeWithCoder:方法中增加此句:

if(self.parent)[encoder encodeObject:self.parent forKey:@"parent"];

同样在initWithCoder:方法中加入:

self.parent=[decoder decodeObjectForKey:@"parent"];

这样,在makeMyClassInstance方法中,我们可以为obj对象构造另一个MyClass对象作为他的parent属性:

MyClass* parent=[[MyClass alloc]init];

parent.name=@"dad";

parent.age=obj.age+20;

parent.sex=0;

parent.parent=nil;

obj.parent=parent;

在反归档之后,我们可以在initUI方法中显示parent的信息:

lbParent.text=obj.parent.name;

程序运行结果如下所示:




    
[2] popupwindow 中 EditText与 软键盘 的有关问题与探索
    来源: 互联网  发布时间: 2014-02-18
popupwindow 中 EditText与 软键盘 的问题与探索

遇到一个问题, 情况是这样的:

一个Activity,上面只有一个录音按钮。

一个popupWindow,点击录音按钮,发出命令,弹出popupwindow。

popwindow里面有一个EditText,点击文本框,就要弹出软键盘,进行手写输入。点击喇叭,就可以切换到语音输入。从手写输入到语音录入切换的时候不能

关闭popupwindow,否则前面输入的内容就没了。

现在有一个矛盾:

                 A、要想在点击EditText的时候能弹出软键盘,就得设置popupwinodw.setFocusable(true);

 B、要在点击popupwindow外面的喇叭button时,不让popupwinodw消失,就得设置popupwindow.setFocusable(false)

这两上水火不容。


后来千辛万苦找到了一种方法:

第一步:popupwindow.setFocusable(false);

第二步:手动给EditText设置onTouch监听,弹出软键盘:

InputMethodManager m = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
                        m.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);

但又悲剧的发现,这弹出的软键盘出现在popupwinow的底层,被popupwindow遮住了。

各位大神,看懂了我表达的意思没?如果理会了,望支招啊!!!

下面是情景图

                                                  



    
[3] GridView实现一起显示并左右滚动
    来源: 互联网  发布时间: 2014-02-18
GridView实现一行显示并左右滚动
使用GridView达到Gallery效果
[html] view plaincopy
  • <?xml version="1.0" encoding="utf-8"?>  
  • <!-- res/layout/gridview_to_gallery.xml -->  
  • <HorizontalScrollView  xmlns:android="http://schemas.android.com/apk/res/android"  
  •     android:layout_width="fill_parent"  
  •     android:layout_height="wrap_content"  
  •     android:scrollbars="none">  
  •         <LinearLayout   
  •             android:layout_width="fill_parent"  
  •             android:layout_height="fill_parent"   
  •             android:orientation="horizontal">  
  •             <GridView android:id="@+id/grid"  
  •                 android:layout_width="1300dp"  
  •                 android:layout_height="fill_parent"  
  •                 android:gravity="center"  
  •                 android:columnWidth="100dip"  
  •                 android:horizontalSpacing="10dip"  
  •                 android:verticalSpacing="10dip"/>  
  •         </LinearLayout>  
  • </HorizontalScrollView>  

  • [java] view plaincopy
  • public class GridViewDemo extends Activity {  
  •     @Override  
  •     public void onCreate(Bundle savedInstanceState) {  
  •         super.onCreate(savedInstanceState);  
  •         setContentView(R.layout.gridview_to_gallery);  
  •           
  •         GridView gridview = (GridView) findViewById(R.id.grid);  
  •         ImageAdapter adapter = new ImageAdapter(this);//一个继承BaseAdapter的自定义适配器  
  •         adapter.setImages(getImages());  
  •         gridview.setAdapter(adapter);  
  •         gridview.setNumColumns(adapter.getCount());  
  •   
  •         gridview.setOnItemClickListener(new OnItemClickListener() {  
  •             @Override  
  •             public void onItemClick(AdapterView<?> av, View v, int position, long id) {  
  •                 Toast.makeText(GridViewDemo.this, "" + position, Toast.LENGTH_SHORT).show();  
  •             }  
  •         });  
  •     }  
  •     /** 
  •      * 取出SD卡中的图片(也可改为取网络或数据库图片) 
  •      * @return 
  •      */  
  •     private List<Bitmap> getImages() {  
  •         List<Bitmap> list = new ArrayList<Bitmap>();  
  •         for (int i=1; i<=12; i++) {  
  •             String imagePath = "/sdcard/image_0"+i+".jpg";  
  •             if (i >= 10) imagePath = "/sdcard/image_"+i+".jpg";  
  •             list.add(BitmapFactory.decodeFile(imagePath));  
  •         }  
  •         return list;  
  •     }  
  • }  

  •  

    自定义适配器

    [java] view plaincopy
  • public class ImageAdapter extends BaseAdapter {  
  •     private Context mContext;  
  •     private List<Bitmap> images = new ArrayList<Bitmap>();  
  •   
  •     public ImageAdapter(Context c) {  
  •         mContext = c;  
  •     }  
  •   
  •     public List<Bitmap> getImages() {  
  •         return images;  
  •     }  
  •     public void setImages(List<Bitmap> images) {  
  •         this.images = images;  
  •     }  
  •   
  •     public int getCount() {  
  •         return images.size();  
  •     }  
  •   
  •     public Object getItem(int position) {  
  •         return images.get(position);  
  •     }  
  •   
  •     public long getItemId(int position) {  
  •         return 0;  
  •     }  
  •   
  •     // create a new ImageView for each item referenced by the Adapter  
  •     public View getView(int position, View convertView, ViewGroup parent) {  
  •         ImageView imageView;  
  •         if (convertView == null) {  // if it's not recycled, initialize some attributes  
  •             imageView = new ImageView(mContext);  
  •             imageView.setLayoutParams(new GridView.LayoutParams(85, 85));  
  •             imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);  
  •             imageView.setPadding(8, 8, 8, 8);  
  •         } else {  
  •             imageView = (ImageView) convertView;  
  •         }  
  •   
  •         imageView.setImageBitmap(images.get(position));  
  •         return imageView;  
  •     }  
  • }  

  •  


        
    最新技术文章:
    ▪Android开发之登录验证实例教程
    ▪Android开发之注册登录方法示例
    ▪Android获取手机SIM卡运营商信息的方法
    ▪Android实现将已发送的短信写入短信数据库的...
    ▪Android发送短信功能代码
    ▪Android根据电话号码获得联系人头像实例代码
    ▪Android中GPS定位的用法实例
    ▪Android实现退出时关闭所有Activity的方法
    ▪Android实现文件的分割和组装
    ▪Android录音应用实例教程
    ▪Android双击返回键退出程序的实现方法
    ▪Android实现侦听电池状态显示、电量及充电动...
    ▪Android获取当前已连接的wifi信号强度的方法
    ▪Android实现动态显示或隐藏密码输入框的内容
    ▪根据USER-AGENT判断手机类型并跳转到相应的app...
    ▪Android Touch事件分发过程详解
    ▪Android中实现为TextView添加多个可点击的文本
    ▪Android程序设计之AIDL实例详解
    ▪Android显式启动与隐式启动Activity的区别介绍
    ▪Android按钮单击事件的四种常用写法总结
    ▪Android消息处理机制Looper和Handler详解
    ▪Android实现Back功能代码片段总结
    ▪Android实用的代码片段 常用代码总结
    ▪Android实现弹出键盘的方法
    ▪Android中通过view方式获取当前Activity的屏幕截...
    ▪Android提高之自定义Menu(TabMenu)实现方法
    ▪Android提高之多方向抽屉实现方法
    ▪Android提高之MediaPlayer播放网络音频的实现方法...
    ▪Android提高之MediaPlayer播放网络视频的实现方法...
    ▪Android提高之手游转电视游戏的模拟操控
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3