首页 文章 精选 留言 我的

精选列表

搜索[网站开发],共10000篇文章
优秀的个人博客,低调大师

【移动开发】Android应用程序完全退出

前段期间,参加比赛做项目时遇到了一个问题:Android中应用程序弹出退出对话框退出应用程序时,老是出现上一个Activity,于是将在Activity跳转时将其finish()掉,结果还是不行!寻其原因:原来项目中有好多Activity用来显示界面,之间还掺扎着数据信息的交流,我们知道Activity是以栈的方式存放,要想将程序退出,自然得将众多Activity销毁掉了! 后来在网上查阅了一下,找到了解决方法,在此总结一下前辈们知识,使其更加系统化! 1.任务管理器方法(ActivityManager): 首先要说明该方法运行在Android 1.5 API Level为3以上才可以,同时需要权限 1 2 ActivityManager am = (ActivityManager)getSystemService (Context.ACTIVITY_SERVICE); am.restartPackage(getPackageName()); 系统会将,该包下的 ,所有进程,服务,全部杀掉,就可以杀干净了,要注意加上 1 < uses-permission android:name=\"android.permission.RESTART_PACKAGES\"></ uses-permission > 2.Dalvik VM的本地方法: 1 2 android.os.Process.killProcess(android.os.Process.myPid()) //获取PID System.exit( 0 ); //常规java、c#的标准退出法,返回值为0代表正常退出 3.一种比较流行的Android经典完美退出方法: 使用单例模式创建一个Activity管理对象,该对象中有一个Activity容器(具体实现自己处理,使用LinkedList等)专门负责存储新开启的每一个Activity,并且容易理解、易于操作,非常不错! A.MyApplication类(储存每一个Activity,并实现关闭所有Activity的操作) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class MyApplication extends Application { //对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList实现了基于动态数组的数据结构,要移动数据。LinkedList基于链表的数据结构,便于增加删除 private List<Activity> activityList = new LinkedList<Activity>(); private static MyApplication instance; private MyApplication(){ } //单例模式中获取唯一的MyApplication实例 public static MyApplication getInstance() { if ( null == instance) { instance = new MyApplication(); } return instance; } //添加Activity到容器中 public void addActivity(Activity activity) { activityList.add(activity); } //遍历所有Activity并finish public void exit(){ for (Activity activity:activityList) { activity.finish(); } System.exit( 0 ); } } B.在每一个Activity中的onCreate方法里添加该Activity到MyApplication对象实例容器中 1 MyApplication.getInstance().addActivity( this ); C.在需要结束所有Activity的时候调用exit方法 1 MyApplication.getInstance().exit(); 4.广播方式: A. MyAcitivty类说明:Acitivty的子类,基础该类的子类必须实现onCreate 方法,在该类中注册了一个BroadcastReceiver 用于接收退出消息,在接收到消息之后结束自身 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public abstract class MyAcitivty extends Activity { /**负责各个具体 Activity 的显示**/ public abstract void onCreate(); @Override public void onCreate( final Bundle savedInstanceState) { // TODO Auto-generated method stub super .onCreate(savedInstanceState); onCreate(); RegListener(); } /**注册退出事件监听**/ public void RegListener() { ExitListenerReceiver exitre = new ExitListenerReceiver(); IntentFilter intentfilter = new IntentFilter(); intentfilter.addAction( this .getPackageName() + "." + "ExitListenerReceiver" ); this .registerReceiver(exitre, intentfilter); } class ExitListenerReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent i) { ((Activity) context).finish(); } } } B.自己的Activity都继承MyAcitivty,到需要退出程序的时候发送广播 1 2 Intent intent = new Intent(context.getPackageName()+ ".ExitListenerReceiver" ); context.sendBroadcast(intent); 即可。 5.一个技巧方式: A.首先设定一个公用的class:Setting.java,定义一个静态类成员 1 public boolean static isCloseAll= false ; B.然后,在每一个Activity的onResume()加入这一个: 1 2 3 4 5 @Override onResume() { super .onResume(); if (Setting.isCloseAll) finish(); } C.当最后一个Activity需要结束整个程序便执行: 1 2 Setting.isCloseAll= true ; finish(); 6.捕获空指针异常 A.通过异常并在Application的子类中重新注册Thread的 Thread.UncaughtExceptionHandler接口: 1 2 3 4 5 6 7 8 9 10 package com.example.android_uncatchexception; import android.app.Application; public class MyCrashApplication extends Application { @Override public void onCreate() { super .onCreate(); //程序一启动,就将未捕获异常初始化 CrashHandler.getInstance().init(getApplicationContext()); } } 注:记得注册Application B.自定义异常捕获类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package com.example.android_uncatchexception; import java.lang.Thread.UncaughtExceptionHandler; import android.content.Context; import android.util.Log; /** * 自定义异常捕获类 * * @author ZHF */ public class CrashHandler implements UncaughtExceptionHandler { public static final String TAG = "CrashHandler" ; // 程序的Context对象 private Context mContext; /** 单例模式 **/ private CrashHandler() { } /** 懒汉式 **/ private static class CrashHolder { static final CrashHandler crashHandler = new CrashHandler(); } public static CrashHandler getInstance() { return CrashHolder.crashHandler; } public void init(Context context) { mContext = context; // 设置该CrashHandler为程序的默认处理器 Thread.setDefaultUncaughtExceptionHandler( this ); } @Override public void uncaughtException(Thread thread, Throwable ex) { Log.d(TAG, "uncaughtException--->thread" + thread + " name: " + thread.getName() + " id: " + thread.getId() + "exception--->" + ex); String threadName = thread.getName(); if ( "main" .equals(threadName)) { Log.d(TAG, "在主线程的崩溃!" ); } else { //这里我们根据thread name来进行区别对待:可以将异常信息写入文件供以后分析 Log.d(TAG, "在子线程中崩溃!" ); } android.os.Process.killProcess(android.os.Process.myPid()); //杀死该进程 System.exit( 0 ); //退出 } } C.在要退出的地方制造空指针异常即可实现闪退,并且不会弹出ANR对话框 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.example.android_uncatchexception; import android.os.Bundle; import android.app.Activity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { Button mBtn; String str; //不要初始化,为了下面制造空指针异常 @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBtn = (Button) this .findViewById(R.id.button1); mBtn.setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { //NullPointerException System.out.println(str); } }); } } 7.网上还有一些其他方式: A.restartPackage、 B. killBackgroundProcesses 不常用,大家可以自行参考哦~ 本文转自zhf651555765 51CTO博客,原文链接:http://blog.51cto.com/smallwoniu/1248643,如需转载请自行联系原作者

优秀的个人博客,低调大师

iOS开发之仿射变换示例总结

一、平移 接下来我们来看一下CGAffineTransform的平移,在使用CGAffineTransform进行平移的时候,我们要注意坐标系的转换。下方是我们在做UI布局时的坐标系,也就是iOS屏幕的坐标系。左上角是原点,x轴右为正,左为负,y轴上为负,下为正。下方就是iPhone的屏幕坐标系。平移时也是采用下方的坐标系结构。 下方就是对ImageView的平移的效果。分别使用两个Slider来控制左右移动和上下移动。具体运行效果如下所示。 控制平移的代码也是比较简单的,如下所示。x参数为正时则向右移动,x为负数时,向左移动。而参数y为正时,向下移动,y为负值时向上运动。具体代码如下所示: 二、缩放 聊完平移,接下来我我们来看一下仿射变换的缩放。使用CGAffineTransform进行View的缩放也是比较简单的,下方就是对ImageView进行缩放的运行效果。在缩放的过程中分为x方向上的缩放和y方向的缩放。x和y分别表示在x轴和y轴上缩放的倍数,如果x或者y为负数的话,那么将相应的视图翻转后在进行缩放,运行效果如下所示。 实现上述效果也是比较简单的,代码就下方一行,如下所示,x就表示x轴上的缩放量,y就表示y轴上的缩放量。 三、旋转 接下来就来聊聊CGAffineTransform的旋转,直奔主题,下方就是旋转的运行结果。旋转是是按照弧度进行旋转的,一圈是0-2∏,如果弧度为正,则是顺时针旋转,如果弧度为负,则是逆时针旋转。具体运行结果如下所示: 实现上述效果的代码也是比较简单的,具体代码如下所示: 本文转自zsdnr 51CTO博客,原文链接:,http://blog.51cto.com/12942149/1929657如需转载请自行联系原作者

优秀的个人博客,低调大师

Android开发中ANR问题出现及解决

写在前面:Application Not Responding。在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application Not Responding)对话框。用户可以选择“等待”而让程序继续运行,也可以选择“强制关闭”。所以一个流畅的合理的应用程序中不能出现anr,而让用户每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要,这样系统不会显示ANR给用户。默认情况下,在android中Activity的最长执行时间是5秒,BroadcastReceiver的最长执行时间则是10秒。 第一:什么会引发ANR? 在Android里,应用程序的响应性是由Activity Manager和WindowManager系统服务监视的。当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR: 1.在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸) 2.BroadcastReceiver在10秒内没有执行完毕 造成以上两点的原因有很多,比如在主线程中做了非常耗时的操作,比如说是下载,io异常等。 第二:如何避免ANR? 1、运行在主线程里的任何方法都尽可能少做事情。特别是,Activity应该在它的关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建操作。(可以采用重新开启子线程的方式,然后使用Handler+Message的方式做一些操作,比如更新主线程中的ui等) 2、应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。但不再是在子 线程里做这些任务(因为 BroadcastReceiver的生命周期短),替代的是,如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个 Service。(此处需要注意的是可以在广播接受者中启动Service,但是却不可以在Service中启动broadcasereciver,关于原因后续会有介绍,此处不是本文重点) 3、避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现。 总结:anr异常也是在程序中自己经常遇到的问题,主要的解决办法自己最常用的就是不要在主线程中做耗时的操作,而应放在子线程中来实现,比如采用Handler+mesage的方式,或者是有时候需要做一些和网络相互交互的耗时操作就采用asyntask异步任务的方式(它的底层其实Handler+mesage有所区别的是它是线程池)等,在主线程中更新UI。 本文转自 小强测试帮 51CTO博客,原文链接:http://blog.51cto.com/xqtesting/1438553,如需转载请自行联系原作者

优秀的个人博客,低调大师

iOS开发zhiATM机的设计与实现

// // main.m // ATM // #import <Foundation/Foundation.h> #import "ATM.h" #import "Money.h" #import "BankCard.h" int main(int argc, const char * argv[]) { ATM * atm = [[ATM alloc]init]; //atm->_saveMoneyCount = 1000; BankCard * card = [BankCard alloc]; // [card set_cardNumber:@"12345678"]; // [card set_userName:@"张三"]; [atm tellMoney:TypeOfMoneyFake]; [card showCardNumber:@"12345678"]; [card showUserName:@"李四"]; NSLog(@"%@",card); [atm saveMoney:10000]; NSLog(@"%@",atm); [atm getMoney:5000]; NSLog(@"%@",atm); return 0; } #import <Foundation/Foundation.h> #import "BankCard.h" #import "Money.h" @interface ATM : NSObject { //用来记录钱的总数 int _countOfMoney; //存钱数目 int _saveMoneyCount; //取钱数目 int _getMoneyCount; } @property int _countOfMoney; @property int _saveMoneyCount; @property int _getMoneyCount; -(void)saveMoney:(int)saveMoney; -(void)getMoney:(int)getMoney; -(void)tellMoney:(TypeOfMoney)typeOfMoney; @end #import "ATM.h" @implementation ATM @synthesize _countOfMoney = countOfMoney; @synthesize _saveMoneyCount = saveMoneyCount; @synthesize _getMoneyCount = getMoneyCount; -(void)saveMoney:(int)saveMoney { //这里參数名称的命名最好不好和实例变量的名称同样 //假设这样做会发生将实例变量隐藏 不影响执行,可是会有警告 _saveMoneyCount = saveMoney; _countOfMoney = _saveMoneyCount; NSLog(@"%d",_saveMoneyCount); } -(void)getMoney:(int)getMoney { _getMoneyCount = getMoney; _saveMoneyCount -= getMoneyCount; NSLog(@"%d",_getMoneyCount); } -(void)tellMoney:(TypeOfMoney)typeOfMoney { switch (typeOfMoney) { case TypeOfMoneyReal: NSLog(@"真币"); break; case TypeOfMoneyFake: NSLog(@"假币"); break; default: break; } } -(NSString *)description { return [NSString stringWithFormat:@"银行卡结余=%d 存入钱数=%d 取出钱数=%d ",_countOfMoney,_saveMoneyCount,_getMoneyCount]; } @end #import <Foundation/Foundation.h> enum TypeOfMoney { TypeOfMoneyReal,//真币 TypeOfMoneyFake//假币 }; typedef enum TypeOfMoney TypeOfMoney; @interface Money : NSObject @end #import "Money.h" @implementation Money { } @end #import <Foundation/Foundation.h> @interface BankCard : NSObject { /**用来存储银行卡账号*/ NSString * _cardNumber; /**用来存储银行卡使用者姓名*/ NSString * _userName; } -(void)showCardNumber:(NSString *)number; -(void)showUserName:(NSString *)name; @property NSString * _cardNumber; @property NSString * _userName; @end #import "BankCard.h" @implementation BankCard @synthesize _cardNumber = carNumber; @synthesize _userName = userName; -(void)showCardNumber:(NSString *)number { //这里忘记了传參数!!! _cardNumber = number; NSLog(@"%@",_cardNumber); } -(void)showUserName:(NSString *)name { _userName = name; NSLog(@"%@",_userName); } -(NSString *)description { return [NSString stringWithFormat:@"账号:%@ username:%@",_cardNumber,_userName]; } @end 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5284583.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android开发高级进阶——多进程间通信

一. 什么是多进程? 多进程就是多个进程的意思,那么什么是进程呢? 当一个应用在开始运行时,系统会为它创建一个进程,一个应用默认只有一个进程,这个进程(主进程)的名称就是应用的包名。 进程的特点: 进程是系统资源和分配的基本单位,而线程是调度的基本单位。 每个进程都有自己独立的资源和内存空间 其它进程不能任意访问当前进程的内存和资源 系统给每个进程分配的内存会有限制 根据上边的引言和进程的特点可以看出,使用多进程的场景为:需要使apk所使用的内存限制扩大。 二. 进程的等级 按优先级可以分为五类,优先级从高到低排列: Android进程分类 前台进程:该进程包含正在与用户进行交互的界面组件,比如一个Activity。在接收关键生命周期方法时会让一个进程临时提升为前台进程,包括任何服务的生命周期方法onCreate()和onDestroy()和任何广播接收器onReceive()方法。这样做确保了这些组件的操作是有效的原子操作,每个组件都能执行完成而不被杀掉。 可见进程:该进程中的组件虽然没有和用户交互,但是仍然可以被看到。activity可见的时候不一定在前台。一个简单的例子是前台的 activity 使用对话框启动了一个新的 activity 或者一个透明 activity 。另一个例子是当调用运行时权限对话框时(事实上它就是一个 activity!)。 服务进程:该进程包含在执行后台操作的服务组件,比如播放音乐的Service。对于许多在后台做处理(如加载数据)而没有立即成为前台服务的应用都属于这种情况。 请特别注意从onStartCommand()返回的常量,如果服务由于内存压力被杀掉,它表示控制什么发生什么:START_STICKY表示希望系统可用的时候自动重启服务,但不关心是否能获得最后一次的 Intent (例如,可以重建自己的状态或者控制自己的 start/stop 生命周期)。START_REDELIVER_INTENT是为那些在被杀死之后重启时重新获得 Intent 的服务的,直到用传递给 onStartCommand() 方法的 startId 参数调用stopSelf()为止。这里会使用 Intent 和 startId 作为队列完成工作。START_NOT_STICKY用于那些杀掉也没关系的服务。这适合那些管理周期性任务的服务,它们只是等待下一个时间窗口工作。 后台进程:该进程包含的组件没有与用户交互,用户也看不到 Service。在一般操作场景下,设备上的许多内存就是用在这上面的,使可以重新回到之前打开过的某个 activity 。 空进程:没有任何界面组件、服务组件,或触发器组件,只是出于缓存的目的而被保留(为了更加有效地使用内存而不是完全释放掉),只要 Android 需要可以随时杀掉它们。 三. 多进程的创建 Android多进程创建很简单,只需要在AndroidManifest.xml的声明四大组件的标签中增加”android:process”属性即可。命名之后,就成了一个单独的进程。 process分私有进程和全局进程: 私有进程的名称前面有冒号,例如: <service android:name=".MusicService" android:process=":musicservice"/> 全局进程的名称前面没有冒号,例如: <service android:name=".MusicService" android:process="com.trampcr.musicdemo.service"/> 为了节省系统内存,在退出该Activity的时候可以将其杀掉(如果没有人为杀掉该进程,在程序完全退出时该进程会被系统杀掉)。 多进程被创建好了,应用运行时就会对进程进行初始化,如果一个application中有多个进程,在进行全局初始化时,多进程会被初始化多次。 解决办法:判断当前进程,然后做相应的初始化操作。 四. 多进程间的通信IPC IPC:InterProcess Communication,即进程间通信。 我们知道,同一个进程的多个线程是共享该进程的所有资源,但多个进程间内存是不可见的,也就是说多个进程间内存是不共享的。那么进程间是如何进行通信的呢? Android中提供了三种方法: 系统实现。 AIDL(Android Interface Definition Language,Android接口定义语言):大部分应用程序不应该使用AIDL去创建一个绑定服务,因为它需要多线程能力,并可能导致一个更复杂的实现。 Messenger:利用Handler实现。(适用于多进程、单线程,不需要考虑线程安全),其底层基于AIDL。 使用Messenger 如需让服务与远程进程通信,则可使用Messenger为服务提供接口。 定义一个MessengerService继承自Service,并在AndroidManifest.xml中声明并给一个进程名,使该服务成为一个单独的进程。代码如下: MessengerService.java public class MessengerService extends Service{ class IncomingHandler extends Handler{ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case 0: Toast.makeText(getApplicationContext(), "hello, trampcr", Toast.LENGTH_SHORT).show(); break; } } } Messenger mMessenger = new Messenger(new IncomingHandler()); @Nullable @Override public IBinder onBind(Intent intent) { Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); return mMessenger.getBinder(); } } AndroidManifest.xml文件的配置如下: <service android:name=".MessengerService" android:process="com.trampcr.messenger.service"/> MessengerActivity.java public class MessengerActivity extends Activity{ private boolean mBound; private Messenger mMessenger; private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mMessenger = new Messenger(service); mBound = true; } @Override public void onServiceDisconnected(ComponentName name) { mMessenger = null; mBound = false; } }; public void sayHello(View v){ if(!mBound){ return; } Message msg = Message.obtain(null, 0 , 0, 0); try { mMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_messenger); } @Override protected void onStart() { super.onStart(); Intent intent = new Intent(MessengerActivity.this, MessengerService.class); bindService(intent, mServiceConnection, BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); if(mBound){ unbindService(mServiceConnection); mBound = false; } } } 通过以上代码,可以看到Messenger的使用方法: 服务实现一个Handler,由其接收来自客户端的每个调用的回调。 Handler用于创建Messenger对象(对Handler的引用)。 Messenger创建一个IBinder,服务通过onBind()使其返回客户端。 客户端使用IBinder将Messenger(引用服务的Handler)实例化,然后使用后者将Message对象发送给服务。 服务在其Handler中(具体地讲,是在handleMessage()方法中)接收每个Message。 这样,客户端并没有调用服务的“方法”。而客户端传递的“消息”(Message对象)是服务在其Handler中接收的。 以上代码实现的应用,刚打开会弹出一个binding,binding表示打开应用Activity就通过Messenger连接了一个服务进程,然后点击say hello会弹出hello,trampcr,这表示了Activity通过Messenger将Message发送给了服务进程。如下图: MessengerService进程与MessengerActivity之间的通信 使用AIDL AIDL是一种接口描述语言,通常用于进程间通信。 使用AIDL的步骤: 创建AIDL,在main下新建一个文件夹aidl,然后在aidl下新建AIDL文件,这时系统会自动为该文件创建一个包名。 aidl文件中会有一个默认的basicType方法,我们为它增加一个getName方法。代码如下: interface IMyAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); String getName(String nickName); } 以上是我们自己创建的aidl文件,系统还会自动生成aidl代码,所在位置为:build/generated/source/aidl下debug和release,但是此时debug下没有任何东西,可以rebuild或运行一下程序,再次打开debug,发现生成了一个包和一个aidl文件。 在java下新建一个类AIDLService继承自Service。代码如下: public class AIDLService extends Service { IMyAidlInterface.Stub mStub = new IMyAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public String getName(String nickName) throws RemoteException { return "aidl " + nickName; } }; @Nullable @Override public IBinder onBind(Intent intent) { return mStub; } } 在AndroidManifest.xml中注册,并给一个进程名,是该服务成为一个独立的进程。 <service android:name=".AIDLService" android:process="com.aidl.test.service"/> 在MainActivity中进行与AIDLService之间的进程间通信。代码如下: public class MainActivity extends AppCompatActivity { private Button mBtnAidl; private IMyAidlInterface mIMyAidlInterface; ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBtnAidl = (Button) findViewById(R.id.btn_aidl); bindService(new Intent(MainActivity.this, AIDLService.class), mServiceConnection, BIND_AUTO_CREATE); mBtnAidl.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(mIMyAidlInterface != null){ try { String name = mIMyAidlInterface.getName("I'm nick"); Toast.makeText(MainActivity.this, "name = " + name, Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); } } } }); } } 在Activity中利用bindService与AIDLService进行连接,通过IMyAidlInterface实例与AIDLService进程进行通信,如下图所示: AIDLService进程与MainActivity之间的通信.gif 五.序列化插件 Parcelable code generate:自动生成实现了Parcelable接口的对象。 本文转自 一点点征服 博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/8417692.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

iOS应用开发之Persistence持久化[转]

持久化(Persistence) 持久化(Persistence)意思就是当你退出app的时候它还会存在。NSUserDefaults就是一个非常简单的持久化方案,不过这有限制,它只能是很小的东西,通常是些用户选项。 如何把那些大数据的东西持久化? 第一个方法,把东西持久化的第一个简单的方式有点像用NSUserDefaults里的property list来实现的进化版,property list是我们自定义的一个概念,是NSArray、NSDictionary、NSNumber、NSString、 NSDate和NSData的组合。所有以上这些都有API可以用来保存,NSUserDefaults也有些API可以。 NSData、NSArray和NSDictionary里还有很重要的方法writeToURL:atomically:,这个方法就是把一个array写到一个文件系统中URL表示的地方,atomically就是如果文件已经存在,它会把文件移到一边,然后写到一个新的文件,关掉这个新的文件。实际上就是写到一个临时命名的文件,然后关掉,把另一个移走,有点原子化操作的感觉,不能写到一半就停下来。writeToURL之后,为了把东西取回来,可以用initWithContentsOfURL或者dataWithContentsOfURL。这些读写方法,不管是发送到NSData或者NSArray或者NSDictionary,就是想让一个相同类型的对象去读回来,它的内部可以就是些property list的东西。 还有另一个类叫做NSPropertyListSerialization,它所做的事情就是把property list转化成NSData,反之亦然。这样它可以将property list转化成一堆二进制数,然后就可以写到磁盘上,或储存到网络。也可以通过网络读取一堆二进制数再通过NSPropertyListSerialization把它们转化回property list。 关于存储的另外一个方法就是通过对象的映像图(arbitrary graphs)来进行归档对象(Archiving Objects)的保存。 把东西存储到文件系统当中。 然后是SQLite 关于持久化存储的重头部分就是Core Data,这是在SQL上层的一个面向对象的数据库机制。 Archiving 在做对象图归档的时候有很多陷阱,归档很适合做循环图。Archiving能发现指针实际所指的对象或者指针相互指着,然后当unarchives的时候又恢复那个指针。但你要考虑清楚来使你构建的对象图有意义,最好的例子可能是在xcode里面建立的view层级。 当从对象库中拖一些东西到屏幕上,就是在实例化UIView,实例化UIViewController,它们都是generic的,所以才需要去inspector面板来改变它们的类。 基本上就是在这个图里面的对象都必须实现NSCoding这个protocol,然后这个protocol里面有两个重要方法: - (void)encodeWithCoder:(NSCoder *)coder; - initWithCoder:(NSCoder *)coder; 第一个是把自己放进archive,第二是把你从archive中取出来用的。这就是viewController出现在storyboard时不用调用它们的指定初始化的原因,因为它们用了这套初始化。这套归档系统在对它们做alloc initWithCoder,因为它们之前用encodeWithCoder把自己保存起来了。在UIView里没有调用initWithFrame,而是用frame对应的encodeWithCoder和initWithCoder来代替。 - (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; [coder encodeFloat:scale forKey:@“scale”]; [coder encodeCGPoint:origin forKey:@“origin”]; [coder encodeObject:expression forKey:@“expression”]; } 必须保证initWithCoder和encodeWithCoder是相对应的。 - initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; scale = [coder decodeFloatForKey:@“scale”]; expression = [coder decodeObjectForKey:@“expression”]; origin=[coderdecodeCGPointForKey:@“origin”]; //notethatorderdoesnotmatter } 怎么来实现这些呢?NSKeyedArchiver中的类方法: + (NSData *)archivedDataWithRootObject:(id <NSCoder>)rootObject; 可以传递一个根对象,比如在storyboard里面的根对象就可能是顶层的view controller。你要做的就是确保里面所有的对象都实现NSCoder协议。 NSKeyedUnarchiver中的类方法: + (id <NSCoder>)unarchiveObjectWithData:(NSData *)data; 这正好相反,你提供一个已经归档的NSData,然后返回被encode的根对象。 id <NSCoder> object = ...; NSData *data = [NSKeyedArchiver archivedDataWithRootObject:object]; id <NSCoder> dup = [NSKeyedArchiver unarchiveObjectWithData:data]; 如果有一个对象,通过第二行将得到关于这个对象的NSData。 如果encode一个view使它的super view被归档,你会被拒绝,除非它处于正确的层级,如果它在顶部它会被拒绝,但如果在内部,就会执行。 File System ios是基于Unix的,底层都是Unix的文件系统,这里有文件系统保护,不可能看到所有的东西,而且也不能随意的写入。 只能在sandbox中做写入,为什么?为了安全。当在设备上删除app时,也会删除所有相关的数据。通过在sandbox中进行写操作,所有应用程序的东西不管是用户创建的还是应用程序自己在sandbox里面创建的一旦移除,所有的都会被移除。 sandbox到底是什么?这里面有应用程序的bundle目录,应用程序不是单独的大的二进制文件,它实际上是一个目录,里面有可执行程序、二进制文件、storyboard及拖进来的图片,所有东西都在里面,这就是应用程序的bundle。sandbox里的目录本身是不可写的,不能在目录里写入东西。这基本上就是一个用xcode创建的app的只读副本。documents目录是sandbox中的一个重要目录,这些地方是用来存储那些被用户视为是自己的文档的。还有一个缓存目录,这里都是一些我们写出来的东西,用户一般不会认为这些是文档,而且这些文档的存在都很短暂,没有了也不会影响到用户。documentation里的关键东西是NSSearchPathDirectory。 如何才能得到这些目录,如何得到这些目录的URL?如果想在application目录中写入,但又不能写入,那么要做的就是将application包里面的东西拷贝到sandbox中任意一个可写的地方然后在那里写入。如果你想将一个数据库连接到你的app,或写入那些数据库,得将它们拷贝出来,无论是拷到文档目录,或是缓存目录,总之是可以写入了。 如何搞到这些目录的路径呢?使用这个方法: - (NSArray *)URLsForDirectory:(NSSearchPathDirectory)directory inDomains:(NSSearchPathDomainMask)domainMask; //NSUserDomainMask NSURL中有个API可以获得一个URL的清单,但得传入想要的目录类型,譬如文档目录、缓存目录。以上方法和NSURL的方法,它们返回一个路径的array,所以当我请求缓存目录时,将得到一个URL的array,或是路径字符串的数组。 NSFileManager为文件系统提供实用操作,这不是用来读写它们自身文件的类。你可以用它来找出文件到底有多大,删除那些陈旧的需要被踢出的缓存文件,也可以用它来找出譬如当应用程序启动时,缓存里面都有哪些文件。它是线程安全的,只要不在两个不同的线程中使用同一个实例。 NSString也有一些文件系统有关的东西,特别是制作路径,一般用NSURL来指定一个链接,有时会用字符串来构建URL。 - (NSString *)stringByAppendingPathComponent:(NSString *)component; 这可以在一个路径中添加内容。还可以把字符串的内容写到文件里去,必须要指定用哪种编码,譬如ASCII、ISOLatin1, - (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag encoding:(NSStringEncoding)encoding //e.g.ASCII,ISOLatin1,etc. error:(NSError **)error; 也可以从文件读取string: - (NSString *)stringWithContentsOfFile:(NSString *)path usedEncoding:(NSStringEncoding *)encoding error:(NSError **)error; SQLite SQLite是指SQL文件保存在单一一个文件里,存储在一个单一的文件中,它速度很快,只占用很小的内存。它基于事务处理,是真正的SQL。这不是基于服务器的SQL,而是基于文件的,所以它是并发性的。如果app中有两个线程,都要写入到SQL数据库中,这可以正常运行。但它只是做简单的锁线程和并发。 以下就是它的API: intsqlite3_open(constchar*filename,sqlite3**db); //get a database into db int sqlite3_exec(sqlite3 *db, // execute SQL statements const char *sql, int (*callback)(void *, int, char **, char **), void *context, char **error); int mycallback(void *context,int count,char **values,char **cols); //data returned int sqlite3_close(sqlite3 *db); // close the database 当你打开SQL文件时,你会得到一个SQL数据库指针,然后要执行SQL语句。向数据库递交你的SQL语句,一些SQL语句就会回调然后在一张表中将你请求的数据返回给你,返回的也可能是error。回调函数通常是这样的格式: int mycallback(void *context,int count,char **values,char **cols); 然后就可以关闭了。你要做的就是第三行const char *sql,这是执行SQL语句的地方。 from:http://www.cnblogs.com/geory/archive/2013/03/11/2953294.html 欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,转载请注明出处! 本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sunshine-anycall/p/3446606.html ,如需转载请自行联系原作者

优秀的个人博客,低调大师

【移动开发】Android波纹动画效果实现

今天我实现一个wifi当中搜索时的动画效果,通常我们会使用多张图片进行Frame动画播放,这里我使用了Tween动画,仅对一张图片进行操作,实现了wifi扫描动画效果,有兴趣的可以看看! 效果图: 这里我们采用了自定义布局的方式 activity_main.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 < RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android" xmlns:tools = "http://schemas.android.com/tools" android:layout_width = "match_parent" android:layout_height = "match_parent" > < com.zhf.android_ripple.AnimationFrameLayout android:id = "@+id/search_animation_wf_main" android:layout_width = "fill_parent" android:layout_height = "fill_parent" > </ com.zhf.android_ripple.AnimationFrameLayout > < Button android:id = "@+id/button1" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_alignParentRight = "true" android:text = "开启波纹动画" /> </ RelativeLayout > AnimationFrameLayout类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 package com.zhf.android_ripple; import java.lang.ref.SoftReference; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationSet; import android.view.animation.ScaleAnimation; import android.widget.FrameLayout; import android.widget.ImageView; public class AnimationFrameLayout extends FrameLayout { private SoftReference<Bitmap> m_bitmapRipple; //波纹图片 (软引用) private ImageView[] m_imageVRadars; //ImageView数组 public AnimationFrameLayout(Context context) { super (context); init(); } public AnimationFrameLayout(Context context, AttributeSet attrs, int defStyle) { super (context, attrs, defStyle); init(); } public AnimationFrameLayout(Context context, AttributeSet attrs) { super (context, attrs); init(); } /**初始化**/ private void init() { loadRadarBitmap(); m_imageVRadars = new ImageView[ 3 ]; View v = LayoutInflater.from(getContext()).inflate(R.layout.wt_search_device_anima, this ); m_imageVRadars[ 0 ] = (ImageView) v.findViewById(R.id.radar_ray_1); m_imageVRadars[ 1 ] = (ImageView) v.findViewById(R.id.radar_ray_2); m_imageVRadars[ 2 ] = (ImageView) v.findViewById(R.id.radar_ray_3); } /**加载图片**/ private void loadRadarBitmap() { try { //获取波纹图片 m_bitmapRipple = new SoftReference<Bitmap>(BitmapFactory.decodeStream(getContext().getResources() .openRawResource(R.drawable.wifi_body_ripple))); } catch (Exception localException) { Log.e( "WTSearchAnimationFrameLayout" , Log.getStackTraceString(localException)); } catch (OutOfMemoryError localOutOfMemoryError) { Log.e( "WTSearchAnimationFrameLayout" , Log.getStackTraceString(localOutOfMemoryError)); System.gc(); //回收 } } /**重置,停止动画**/ public void stopAnimation() { for ( int i= 0 ; i< m_imageVRadars.length; ++i) { if (m_bitmapRipple != null ){ Bitmap localBitmap = m_bitmapRipple.get(); //软引用获取对象 if (localBitmap != null && !localBitmap.isRecycled()) { //回收图片资源 localBitmap.recycle(); } m_bitmapRipple = null ; ImageView localImageView = m_imageVRadars[i]; localImageView.setImageBitmap( null ); //设置ImageView为空 localImageView.setVisibility(View.GONE); localImageView.clearAnimation(); //取消动画 } } } /**开始动画**/ public void startAnimation() { if (m_bitmapRipple == null ) { loadRadarBitmap(); } for ( int i = 0 ; i < m_imageVRadars.length; i++) { ImageView localImageView; long ltime; while ( true ) { localImageView = m_imageVRadars[i]; localImageView.setImageBitmap(m_bitmapRipple.get()); //获取图片 localImageView.setVisibility(View.VISIBLE); //放大 ltime= 333L * i; if (localImageView.getAnimation() == null ) { break ; } localImageView.getAnimation().start(); } ScaleAnimation localScaleAnimation = new ScaleAnimation( 1 .0f, 14 .0f, 1 .0f, 14 .0f, 1 , 0 .5f, 1 , 0 .5f); localScaleAnimation.setRepeatCount(- 1 ); //动画重复 AlphaAnimation localAlphaAnimation = new AlphaAnimation( 1 .0f, 0 .2f); AnimationSet localAnimationSet = new AnimationSet( true ); //true:使用相同的加速器 localAnimationSet.addAnimation(localScaleAnimation); localAnimationSet.addAnimation(localAlphaAnimation); //将两种动画效果添加进去 //设置相关属性 localAnimationSet.setDuration(1000L); //持续时间 localAnimationSet.setFillEnabled( true ); localAnimationSet.setFillBefore( true ); //控件保持在动画开始之前 localAnimationSet.setStartOffset(ltime); //动画效果推迟ltime秒钟后启动 localAnimationSet.setInterpolator( new AccelerateDecelerateInterpolator()); localAnimationSet.setAnimationListener( new MySearchAnimationHandler( this ,localImageView)); //绑定监听器 //将动画集合设置进去 localImageView.setAnimation(localAnimationSet); localImageView.startAnimation(localAnimationSet); //开启动画 } } /**动画监听类**/ public class MySearchAnimationHandler implements AnimationListener{ private ImageView m_imageVRadar; public MySearchAnimationHandler(AnimationFrameLayout paramImageView,ImageView m_imageVRadar) { super (); this .m_imageVRadar = m_imageVRadar; } @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { this .m_imageVRadar.setVisibility(View.GONE); } @Override public void onAnimationRepeat(Animation animation) { animation.setStartOffset(0L); } } } 重要说明: 1.该类中我们对图片的操作使用软引用,目的是防止OOM. 2.至于动画,使用ImageView[]来依次加载图片,通过更改对每个ImageView实现缩放和透明动画 动画布局 wt_search_device_anima.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <? xml version = "1.0" encoding = "utf-8" ?> < RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android" android:layout_width = "fill_parent" android:layout_height = "fill_parent" > < ImageView android:id = "@+id/radar_ray_1" android:layout_width = "70.0dip" android:layout_height = "70.0dip" android:layout_alignParentRight = "true" android:layout_alignParentTop = "true" android:layout_marginLeft = "10.0dip" /> < ImageView android:id = "@+id/radar_ray_2" android:layout_width = "70.0dip" android:layout_height = "70.0dip" android:layout_alignParentRight = "true" android:layout_alignParentTop = "true" android:layout_marginLeft = "10.0dip" /> < ImageView android:id = "@+id/radar_ray_3" android:layout_width = "70.0dip" android:layout_height = "70.0dip" android:layout_alignParentRight = "true" android:layout_alignParentTop = "true" android:layout_marginLeft = "10.0dip" /> </ RelativeLayout > 程序主入口: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package com.zhf.android_ripple; import android.os.Bundle; import android.app.Activity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { public Button m_btn1; AnimationFrameLayout afl; //动画布局 @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); afl = ((Animat ionFrameLayout) findViewById(R.id.search_animation_wf_main)); // 搜索时的动画 m_btn1 = (Button) findViewById(R.id.button1); m_btn1.setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { afl.startAnimation(); } }); } @Override protected void onDestroy() { // TODO Auto-generated method stub super .onDestroy(); afl.stopAnimation(); } } ok! 源码已添加!试试效果吧! 本文转自zhf651555765 51CTO博客,原文链接:http://blog.51cto.com/smallwoniu/1334425,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android UI开发第三篇——popupwindow

PopupWindow在android.widget包下,弹出窗口的形式展示。官方文档对该控件的描述是:“一个弹出窗口控件,可以用来显示任意视图(View),而且会浮动在当前 活动(activity)的顶部”。PopupWindow可以让我们实现多种自定义控件,例如:menu、alertdialog等弹窗似的View。 popupwindow需要在onCreate时初始化、通过触发事件展示出来。 public class ShowPopupWindow extends Activity implements View.OnClickListener{ View view; PopupWindow pop; Button btnShowAsDrawDown; Button btnShowAsDrawDown1; Button btnShowAtLocation; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.popup_activity); btnShowAsDrawDown = (Button)findViewById(R.id.btnShowAsDrawDown); btnShowAsDrawDown.setOnClickListener(this); btnShowAsDrawDown = (Button)findViewById(R.id.btnShowAsDrawDown1); btnShowAsDrawDown.setOnClickListener(this); btnShowAtLocation = (Button)findViewById(R.id.btnShowAt); btnShowAtLocation.setOnClickListener(this); initPopupWindow(); } @Override public void onClick(View v) { // TODO Auto-generated method stub switch(v.getId()) { case R.id.btnShowAsDrawDown: if(pop.isShowing()) { pop.dismiss(); } else { pop.showAsDropDown(v); } break; case R.id.btnShowAsDrawDown1: if(pop.isShowing()) { pop.dismiss(); } else { pop.showAsDropDown(v, 0, -160); } break; default: if(pop.isShowing()) { pop.dismiss(); } else { pop.showAtLocation(findViewById(R.id.main), Gravity.CENTER_HORIZONTAL, 0, 0); } break; } } private void initPopupWindow() { view = this.getLayoutInflater().inflate(R.layout.popup_window, null); pop = new PopupWindow(view, ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); pop.setOutsideTouchable(true); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub pop.dismiss(); } }); } } popup_activity.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:id="@+id/main" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="pop demo!" /> <Button android:id="@+id/btnShowAsDrawDown" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Show as drawndown(one parameter)" /> <Button android:id="@+id/btnShowAsDrawDown1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Show as drawndown(three parameters)" /> <Button android:id="@+id/btnShowAt" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Show At Location" /> </LinearLayout> popup_window.xml <?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" android:orientation="vertical" android:gravity="center_horizontal" android:background="#d3d3d3"> <Button android:id="@+id/btn_pop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Close" android:layout_margin="10dip" /> </LinearLayout> 本文转自xyz_lmn51CTO博客,原文链接:http://blog.51cto.com/xyzlmn/817389 ,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android开发入门必知:应用界面组成

屏幕是简化的窗口,在Android中,常常使用的就是这种简单的“窗口”。屏幕和屏幕中的内容是Android中UI构建的主要内容。这两个方面包括: 屏幕:活动(android.app.Activity); 屏幕中的内容:视图(android.view.View)。 Android中屏幕及其中内容的程序结构如图2-1所示。 ▲图2-1 Android中屏幕及其中内容的程序结构 如图2-1所示,android.app包中的Activity和android.view包中的View分别用于表示一个屏幕和一个视图的基类。 Android用户界面的基本构建方法分成以下几个步骤: 继承默认Activity实现自己的屏幕; 使用View的继承者作为屏幕中的内容; 响应屏幕及其内容中的事件。 屏幕(活动Activity) android.app.Activity类是Android中的活动,是Android四种组件中用来表示UI方面的组件。一个Activity中最主要的内容就是一个视图(View),此外,这个类还包含了标题栏、菜单、对话框附属功能。 活动的生命周期如图2-2所示。 ▲图2-2 活动的生命周期 在应用程序中实现自己的活动的时候,通常需要继承一个Activity类,并主要实现Activity中的以下几个protected的方法: protected void onCreate (Bundle savedInstanceState) // 创建时调用 protected void onStart () // 开始时调用 protected void onResume () // 恢复时调用 protected void onPause () // 停止时调用 protected void onStop () // 完全停止时调用 protected void onRestart () // 重新开始时调用 protected void onDestroy () // 销毁时调用 这些以on为开头的方法用于指定一个活动的状态机转换时刻的行为,将在一个活动生命周期中运行的不同阶段被调用。 在一个Activity中,提供了以下一些接口来设置其中的内容: public void setContentView(int layoutResID) // 以布局文件的方式来设置 public void setContentView(View view) // 以视图类的方式来设置 public void setContentView(View view, ViewGroup.LayoutParams params) setContentView()用于将一个视图(View)设置到活动中,通常在所实现Activity的onCreate()阶段被调用。 屏幕中的内容(视图View) android.view.View表示可见的视图内容,它表现为界面上的可视内容,也可以接收事件。在程序中具体使用的类一般是View的继承者。各种View的继承者可以在布局文件中被描述。 View的主要标识是它的id,查找子View的方法。 public final View findViewById(int id) View的事件主要由其中的监听者(Listener)来获得,在View类中具有setOn{XXX}Listener()系列方法,内容如下所示: public void setOnClickListener(View.OnClickListener l); public void setOnLongClickListener(View.OnLongClickListener l); public void setOnFocusChangeListener(View.OnFocusChangeListener l); public void setOnKeyListener(View.OnKeyListener l); public void setOnTouchListener(View.OnTouchListener l); public void setOnCreateContextMenuListener(View.OnCreateContextMenuListener l) 这些方法的参数分别为android.view包中的几个接口,如表2-1所示。 表2-1 事件处理接口 监听者功能监 听 类接口中的方法 单击OnClickListenervoid onClick(View v) 长按OnLongClickListenerboolean onLongClick(View v) 焦点变化OnFocusChangeListenervoid onFocusChange(View v, boolean hasFocus) 按键OnKeyListenerboolean onKey(View v, int keyCode, KeyEvent event) 触摸OnTouchListenerboolean onTouch(View v, MotionEvent event) 上下文菜单OnCreateContextMenuListenervoid onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) 这些接口通常需要被用户程序实现。需要实现的方法中,均以View为第一个参数,当这些方法被调用的时候,传入的第一个参数通常就是发生事件的View。 二者的结合 View及其继承者通常可以设置到Activity中,作为其中的内容来使用。设置的方法通常是使用Activity的setContentView()方法。 例如使用如下的方法将一个布局文件设置到活动当中。 setContentView(R.layout.mylayout); 布局文件可以转化成View类。这是需要使用的是android.view包中的LayoutInflater类。此时主要使用类中的以下几个方法: public View inflate (int resource, ViewGroup root) public View inflate (int resource, ViewGroup root, boolean attachToRoot) public View inflate (XmlPullParser parser, ViewGroup root) public View inflate (XmlPullParser parser, ViewGroup root, boolean attachToRoot) LayoutInflater功能就是根据布局文件的id或者XML文件,将其转化为一个View类型的内容。 在一个活动中进行如下的调用,将布局文件设置到其中: LayoutInflater factory = LayoutInflater.from(this); final View mylayout = (View )factory.inflate(R.layout.mylayout, null); setContentView(mylayout); 这种实现方式等价于上述直接将布局文件设置到Activity中的方式,但是两个setContentView()的参数不同,前者使用的是整数参数,表示布局文件的id,后者使用的是一个View类型。所谓XML格式的布局文件,经过解析之后的结果实际上是一个对多层次组成的View。 提示:Activity中的setContentView()一般设置布局文件即可,没有必要拆成解析和设置两个步骤。在需要View类型的参数时,LayoutInflater可完成布局文件到View的转换。 本文转自 wws5201985 51CTO博客,原文链接:http://blog.51cto.com/wws5201985/798104,如需转载请自行联系原作者

优秀的个人博客,低调大师

64位Linux下配置Android开发环境

1.下载jdk.x86_64并安装(我下的是这个 jdk-7u1-linux-x64.rpm ) rpm -ivh jdk-7u1-linux-x64.rpm 安装完成后,安到了/usr/java/ 由于原先安装了openjdk,所以默认版本还是openjdk 在.bashrc文件添加如下内容(仅对当前用户有效,其他用户默认还是openjdk) 测试 2.安装Eclipse(我下的是Eclipse Classic, eclipse-SDK-3.7.1-linux-gtk-x86_64.tar.gz ) 解压eclipse到某路径 export PATH=某路径/eclipse/bin:$PATH 顺便写到.bashrc里面。 直接在终端输入eclipse打开eclipse。 在Windows->Preferences->Java->Installed JREs里面添加新JRE的路径,并且设为默认。 将兼容性改为1.7 3.安装Android ADT和Android SDK 下载android ADT,我下的版本是ADT-15.0.1.zip,SDK是android-sdk_r15-linux.tgz 打开Help -> Install New Software,点击 Add 随便输入名字,比如android,点击Archieve,选择 ADT-15.0.1.zip 下一步,即使是本地安装,也还需要下点东西 慢的一比啊。 终于完了。 重启Eclipse,出现下面的画面 解压sdk ,在上面输入解压后的路径,下一步。下一些东西后出现 点击安装后,又要下东西,太烦人了,网速相当不给力啊 本文转自nxlhero 51CTO博客,原文链接:http://blog.51cto.com/nxlhero/717903,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android开发学习笔记:Gallery和GridView浅析

一.Gallery的简介 Gallery(画廊)是一个锁定中心条目并且拥有水平滚动列表的视图,一般用来浏览图片,并且可以响应事件显示信息。Gallery还可以和ImageSwitcher组件结合使用来实现一个通过缩略图来浏览图片的效果。 Gallery常用的XML属性 属性名称 描述 android:animationDuration 设置布局变化时动画的转换所需的时间(毫秒级)。仅在动画开始时计时。该值必须是整数,比如:100。 android:gravity 指定在对象的X和Y轴上如何放置内容。指定一下常量中的一个或多个(使用 “|”分割) Constant Value Description top 0x30 紧靠容器顶端,不改变其大小 bottom 0x50 紧靠容器底部,不改变其大小 left 0x03 紧靠容器左侧,不改变其大小 right 0x05 紧靠容器右侧,不改变其大小 center_vertical 0x10 垂直居中,不改变其大小 fill_vertical 0x70 垂直方向上拉伸至充满容器 center_horizontal 0x01 水平居中,不改变其大小 Fill_horizontal 0x07 水平方向上拉伸使其充满容器 center 0x11 居中对齐,不改变其大小 fill 0x77 在水平和垂直方向上拉伸,使其充满容器 clip_vertical 0x80 垂直剪切(当对象边缘超出容器的时候,将上下边缘超出的部分剪切掉) clip_horizontal 0x08 水平剪切(当对象边缘超出容器的时候,将左右边缘超出的部分剪切掉) android:spacing 图片之间的间距 android:unselectedAlpha 设置未选中的条目的透明度(Alpha)。该值必须是float类型,比如:“1.2”。 首先介绍Gallery单独使用的例子: MainActivity.java packagecom.android.gallerydemo; importandroid.app.Activity; importandroid.content.Context; importandroid.os.Bundle; importandroid.view.View; importandroid.view.ViewGroup; importandroid.widget.AdapterView; importandroid.widget.AdapterView.OnItemClickListener; importandroid.widget.BaseAdapter; importandroid.widget.Gallery; importandroid.widget.ImageView; importandroid.widget.Toast; publicclassMainActivityextendsActivity{ privateGallerygallery; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); gallery=(Gallery)findViewById(R.id.gallery); //设置图片适配器 gallery.setAdapter(newImageAdapter(this)); //设置监听器 gallery.setOnItemClickListener(newOnItemClickListener(){ @Override publicvoidonItemClick(AdapterView<?>parent,Viewv,intposition,longid){ Toast.makeText(MainActivity.this,"点击了第"+(position+1)+"张图片",Toast.LENGTH_LONG).show(); } }); } } classImageAdapterextendsBaseAdapter{ //声明Context privateContextcontext; //图片源数组 privateInteger[]imageInteger={ R.drawable.pic1, R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5, R.drawable.pic6, R.drawable.pic7 }; //声明ImageAdapter publicImageAdapter(Contextc){ context=c; } @Override //获取图片的个数 publicintgetCount(){ returnimageInteger.length; } @Override //获取图片在库中的位置 publicObjectgetItem(intposition){ returnposition; } @Override //获取图片在库中的位置 publiclonggetItemId(intposition){ //TODOAuto-generatedmethodstub returnposition; } @Override publicViewgetView(intposition,ViewconvertView,ViewGroupparent){ ImageViewimageView=newImageView(context); //给ImageView设置资源 imageView.setImageResource(imageInteger[position]); //设置比例类型 imageView.setScaleType(ImageView.ScaleType.FIT_XY); //设置布局图片128x192显示 imageView.setLayoutParams(newGallery.LayoutParams(128,192)); returnimageView; } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <Galleryxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gallery" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:background="?android:galleryItemBackground" /> 效果图: Gallery和ImageSwitcher组件结合使用的例子: MainActivity.java packagecom.android.gallerytest; importandroid.app.Activity; importandroid.content.Context; importandroid.os.Bundle; importandroid.view.View; importandroid.view.ViewGroup; importandroid.view.Window; importandroid.view.animation.AnimationUtils; importandroid.widget.AdapterView; importandroid.widget.BaseAdapter; importandroid.widget.Gallery; importandroid.widget.ImageSwitcher; importandroid.widget.ImageView; importandroid.widget.AdapterView.OnItemSelectedListener; importandroid.widget.Gallery.LayoutParams; importandroid.widget.ViewSwitcher.ViewFactory; publicclassMainActivityextendsActivityimplementsOnItemSelectedListener, ViewFactory{ privateImageSwitchermSwitcher; //大图片对应的缩略图源数组 privateInteger[]mThumbIds={R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,R.drawable.sample_thumb_6, R.drawable.sample_thumb_7}; //大图片源数组 privateInteger[]mImageIds={R.drawable.sample_0,R.drawable.sample_1, R.drawable.sample_2,R.drawable.sample_3,R.drawable.sample_4, R.drawable.sample_5,R.drawable.sample_6,R.drawable.sample_7}; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); //设置窗口无标题 requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); mSwitcher=(ImageSwitcher)findViewById(R.id.switcher); //注意在使用一个ImageSwitcher之前, //一定要调用setFactory方法,要不setImageResource这个方法会报空指针异常。 mSwitcher.setFactory(this); //设置动画效果 mSwitcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in)); mSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out)); Galleryg=(Gallery)findViewById(R.id.gallery); //添加OnItemSelectedListener监听器 g.setAdapter(newImageAdapter(this)); g.setOnItemSelectedListener(this); } //创建内部类ImageAdapter publicclassImageAdapterextendsBaseAdapter{ publicImageAdapter(Contextc){ mContext=c; } publicintgetCount(){ returnmThumbIds.length; } publicObjectgetItem(intposition){ returnposition; } publiclonggetItemId(intposition){ returnposition; } publicViewgetView(intposition,ViewconvertView,ViewGroupparent){ ImageViewi=newImageView(mContext); i.setImageResource(mThumbIds[position]); //设置边界对齐 i.setAdjustViewBounds(true); //设置布局参数 i.setLayoutParams(newGallery.LayoutParams( LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)); //设置背景资源 i.setBackgroundResource(R.drawable.picture_frame); returni; } privateContextmContext; } @Override //实现onItemSelected()方法,更换图片 publicvoidonItemSelected(AdapterView<?>adapter,Viewv,intposition, longid){ //设置图片资源 mSwitcher.setImageResource(mImageIds[position]); } @Override publicvoidonNothingSelected(AdapterView<?>arg0){ } @Override //实现makeView()方法,为ImageView设置布局格式 publicViewmakeView(){ ImageViewi=newImageView(this); //设置背景颜色 i.setBackgroundColor(0xFF000000); //设置比例类型 i.setScaleType(ImageView.ScaleType.FIT_CENTER); //设置布局参数 i.setLayoutParams(newImageSwitcher.LayoutParams( LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT)); returni; } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ImageSwitcher android:id="@+id/switcher" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" /> <Gallery android:id="@+id/gallery" android:background="#55000000" android:layout_width="fill_parent" android:layout_height="60dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:gravity="center_vertical" android:spacing="16dp" /> </RelativeLayout> 效果图: 二.GridView的简介 GridView(网格视图)是按照行列的方式来显示内容的,一般用于显示图片,图片等内容,比如实现九宫格图,用GridView是首选,也是最简单的。主要用于设置Adapter。 GridView常用的XML属性: 属性名称 描述 android:columnWidth 设置列的宽度。 android:gravity 设置此组件中的内容在组件中的位置。可选的值有:top、bottom、left、right、center_vertical、fill_vertical、center_horizontal、fill_horizontal、center、fill、clip_vertical可以多选,用“|”分开。 android:horizontalSpacing 两列之间的间距。 android:numColumns 设置列数。 android:stretchMode 缩放模式。 android:verticalSpacing 两行之间的间距。 下面有三个例子,第一个是只显示图片的,第二个是显示图片文字的(这里的图片是Android系统自带的图片),第三个是显示自定义的图片文字。前面两个例子的实现都不是很难,第三个例子的实现有些复杂,学习GridView的时候,就想着能不能自定义自己喜欢的图片加上文字,在网上找些资料,一般都是第二个例子的形式的,最后在视频学习上找到了能实现自定义自己的图片的例子。自己就照着例子去学习,修改成了第三个例子。 第一个例子: MainActivity.java package com.android.gridview.activity; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; import android.widget.Toast; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); GridView gv = (GridView)findViewById(R.id.GridView1); //为GridView设置适配器 gv.setAdapter(new MyAdapter(this)); //注册监听事件 gv.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { Toast.makeText(MainActivity.this, "pic" + position, Toast.LENGTH_SHORT).show(); } }); } } //自定义适配器 class MyAdapter extends BaseAdapter{ //上下文对象 private Context context; //图片数组 private Integer[] imgs = { R.drawable.pic0, R.drawable.pic1, R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5, R.drawable.pic6, R.drawable.pic7, R.drawable.pic8, R.drawable.pic0, R.drawable.pic1, R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5, R.drawable.pic6, R.drawable.pic7, R.drawable.pic8, }; MyAdapter(Context context){ this.context = context; } public int getCount() { return imgs.length; } public Object getItem(int item) { return item; } public long getItemId(int id) { return id; } //创建View方法 public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { imageView = new ImageView(context); imageView.setLayoutParams(new GridView.LayoutParams(75, 75));//设置ImageView对象布局 imageView.setAdjustViewBounds(false);//设置边界对齐 imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);//设置刻度的类型 imageView.setPadding(8, 8, 8, 8);//设置间距 } else { imageView = (ImageView) convertView; } imageView.setImageResource(imgs[position]);//为ImageView设置图片资源 return imageView; } } main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <GridView android:id="@+id/GridView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:columnWidth="90dp" android:numColumns="3" android:verticalSpacing="10dp" android:horizontalSpacing="10dp" android:stretchMode="columnWidth" android:gravity="center" /> </LinearLayout> 效果图: 第二个例子: MainActivity.java package com.android.gridview2.activity; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.widget.GridView; import android.widget.SimpleAdapter; public class MainActivity extends Activity { private GridView gv; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.gridview); //准备要添加的数据条目 List<Map<String, Object>> items = new ArrayList<Map<String,Object>>(); for (int i = 0; i < 9; i++) { Map<String, Object> item = new HashMap<String, Object>(); item.put("imageItem", R.drawable.icon);//添加图像资源的ID item.put("textItem", "icon" + i);//按序号添加ItemText items.add(item); } //实例化一个适配器 SimpleAdapter adapter = new SimpleAdapter(this, items, R.layout.grid_item, new String[]{"imageItem", "textItem"}, new int[]{R.id.image_item, R.id.text_item}); //获得GridView实例 gv = (GridView)findViewById(R.id.mygridview); //为GridView设置适配器 gv.setAdapter(adapter); } } gridview.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" > <GridView android:id="@+id/mygridview" android:numColumns="3" android:gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:stretchMode="columnWidth" /> </LinearLayout> grid_item.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/RelativeLayout1" android:layout_width="wrap_content" android:layout_height="fill_parent" android:paddingBottom="6dip" > <ImageView android:id="@+id/image_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" /> <TextView android:id="@+id/text_item" android:layout_below="@+id/image_item" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_centerHorizontal="true" /> </RelativeLayout> 效果图: 第三个例子: MainActivity.java package com.android.gridview3; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; public class MainActivity extends Activity { private GridView gridView; //图片的文字标题 private String[] titles = new String[] { "pic1", "pic2", "pic3", "pic4", "pic5", "pic6", "pic7", "pic8", "pic9"}; //图片ID数组 private int[] images = new int[]{ R.drawable.pic1, R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5, R.drawable.pic6, R.drawable.pic7, R.drawable.pic8,R.drawable.pic9 }; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); gridView = (GridView) findViewById(R.id.gridview); PictureAdapter adapter = new PictureAdapter(titles, images, this); gridView.setAdapter(adapter); gridView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { Toast.makeText(MainActivity.this, "pic" + (position+1), Toast.LENGTH_SHORT).show(); } }); } } //自定义适配器 class PictureAdapter extends BaseAdapter{ private LayoutInflater inflater; private List<Picture> pictures; public PictureAdapter(String[] titles, int[] images, Context context) { super(); pictures = new ArrayList<Picture>(); inflater = LayoutInflater.from(context); for (int i = 0; i < images.length; i++) { Picture picture = new Picture(titles[i], images[i]); pictures.add(picture); } } @Override public int getCount() { if (null != pictures) { return pictures.size(); } else { return 0; } } @Override public Object getItem(int position) { return pictures.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { convertView = inflater.inflate(R.layout.picture_item, null); viewHolder = new ViewHolder(); viewHolder.title = (TextView) convertView.findViewById(R.id.title); viewHolder.image = (ImageView) convertView.findViewById(R.id.image); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.title.setText(pictures.get(position).getTitle()); viewHolder.image.setImageResource(pictures.get(position).getImageId()); return convertView; } } class ViewHolder { public TextView title; public ImageView image; } class Picture { private String title; private int imageId; public Picture() { super(); } public Picture(String title, int imageId) { super(); this.title = title; this.imageId = imageId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public int getImageId() { return imageId; } public void setImageId(int imageId) { this.imageId = imageId; } } main.xml <?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:columnWidth="90dp" android:numColumns="auto_fit" android:verticalSpacing="10dp" android:horizontalSpacing="10dp" android:stretchMode="columnWidth" android:gravity="center" /> picture_item.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" > <ImageView android:id="@+id/image" android:layout_width="100dp" android:layout_height="150dp" android:layout_gravity="center" android:scaleType="fitXY" android:padding="4dp" /> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center_horizontal" /> </LinearLayout> 效果图: 本文转自 lingdududu 51CTO博客,原文链接:http://blog.51cto.com/liangruijun/647355

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册