【Android游戏开发十七】让玩家自定义手势玩转Android游戏!

简介:

    有童鞋问我为什么不用SDK2.1 ,2.2来进行游戏开发,那我这里稍微说两句:

    1.Android SDK 属于向下兼容!那么低版本可以运行的,高版本基本上更是没问题!(当然每次SDK的更新也会带来新功能,或者修改了一些原来的BUG等等,那么其实对于游戏开发来说,如果你的游戏中不需要更高的SDK版本的支持情况下,完全不必去追求最新的SDK!)

    2.使用低版本进行游戏开发这样能兼顾更多的机型,获取更多的用户!

    3.大家都知道Android SDK 每次版本的更新,底层代码也会更健壮和优化了!比如我们公司的网游Android版在G2(SDK1.5)上跑起来稍微有些卡,而在我的手机上(SDK2.2)运行起来流畅的没说的~各种舒坦~~但是这样也会带来一些弊端,比如我们自己游戏如果上来就用高版本SDK进行开发,那么对于性能、内存上到底如何,我们都不会很容易的看出其效果,如果我们用低版本的SDK则会让我们明显的感受到性能到底如何~你想想如果你的游戏在1.5 ,1.6上跑起来很流畅,那放在更高版本的SDK机器上更是没说的啦~

    总结:游戏开发中,如果你游戏不需要更高的API的支持,那么推荐基于SDK 1.5和1.6来开发!

     在上一篇中我给大家介绍了触摸屏手势操作,但是这种触屏手势的操作比较有局限性;比如我们都知道Android可以利用手势来解锁,比如九宫格形式的,通过自定义的一个单笔画手势可以解开屏幕锁,还可以自定义笔画手势来启动一个应用等,那么这种所谓的笔画手势其实就是今天我要给大家讲解的输入法手势识别技术!这种手势是我们可以自己来自定义,而不像之前的触屏手势操作只是利用Android 对一些触屏动作的封装罢了。下面上几张手机自定义笔划手势解锁的的截图: 

  

 左图中最后一个是自定义解锁的输入法手势~ 

    OK,那么既然利用手势既然能进行解锁等操作,那么我们游戏开发中,更是可以加入这一亮点了,比如在游戏中我画个圆形执行换背景操作,画个X表示退出游戏等等,等等、哈哈 是不是感觉很有意思了?好的,下面就开始进入讲解!

 首先本篇主要学习两点:

    1. 如何创建输入法手势、删除输入法手势、从SD卡中读取出手势文件!

    2.当输入法手势创建后,如何来匹配出我们的自定义手势!

 

下面我们来熟习两个类和几个概念:

     1. 什么是 GestureOverlayView ? 简单点说其实就是一个手写绘图区;

     2. 什么是 GestureLibrary ? 这个类是对手势进行保存、删除等操作的,一个存放手势的小仓库!

    3. 笔划是什么,字体笔画? 是的,其实就是跟我们写字的笔划一个概念!

   4.什么是笔类型? 输入法手势操作中,笔划类型有两种;一种是:单一笔划,另外一种是:多笔划

    所谓单一笔划笔划就是一笔划画出一个手势,从你手指接触屏幕开始到你离开屏幕笔画就会立刻形成一个手势!一气呵成!

    而多笔划则是可以在一定紧凑时间内随意几笔划都可!然后超过这个紧凑时间后便会形成一个手势!

   先出项目截图,简单说下其功能和操作:

【图1】 【图2】 

 

     图1界面中分为3块,从上到下依次是:TextView ,EditText,SurfaceView;然后在SurfaceView后面还有一个覆盖全屏的GestureOverlayView!

    图2界面是在创建好的手势中匹配手势的界面,这里很清晰看出来,找的很对 ~嘿嘿~

 先看下main.xml:  


  
  
  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:orientation="vertical" android:layout_width="fill_parent" 
  4.     android:layout_height="fill_parent"> 
  5.     <TextView android:id="@+id/himi_tv" android:layout_width="fill_parent" 
  6.         android:layout_height="wrap_content" android:text="@string/hello" 
  7.         android:textSize="15sp" android:textColor="#FFFFFF00" /> 
  8.     <EditText android:id="@+id/himi_edit" android:layout_width="fill_parent" 
  9.         android:layout_height="wrap_content" /> 
  10.     <RelativeLayout android:layout_width="fill_parent" 
  11.         android:layout_height="wrap_content" android:layout_weight="1"> 
  12.         <com.himi.MySurfaceView android:id="@+id/view3d" 
  13.             android:layout_width="fill_parent" android:layout_height="fill_parent" /> 
  14.         <android.gesture.GestureOverlayView 
  15.             android:id="@+id/himi_gesture" android:layout_width="fill_parent" 
  16.             android:layout_height="fill_parent" android:layout_weight="1.0"/> 
  17.     </RelativeLayout> 
  18. </LinearLayout> 

     xml中注册的有我们自定义的surfaceview,对此不太熟悉可以去看下【Android2D开发之六】,不多解释了。关于GestureOverlayView这里也只是简单的定义了宽高,还有一些重要的属性设置在代码中设置了,当然xml也可以设置的;

 下面看MainActivity.java  


  
  
  1. **  
  2.  *@author Himi  
  3.  *@输入法手势识别  
  4.  *@注意: android.gesture这个类在api-4(SDK1.6)才开始支持的!  
  5.  *@提醒:默认存到SD卡中,所以别忘记在AndroidMainfest.xml加上SD卡读写权限!  
  6.  */  
  7. public class MainActivity extends Activity {  
  8.     private GestureOverlayView gov;// 创建一个手写绘图区  
  9.     private Gesture gesture;// 手写实例  
  10.     private GestureLibrary gestureLib;//创建一个手势仓库  
  11.     private TextView tv;  
  12.     private EditText et;  
  13.     private String path;//手势文件路径  
  14.     private File file;//  
  15.     @Override  
  16.     public void onCreate(Bundle savedInstanceState) {  
  17.         super.onCreate(savedInstanceState);  
  18.         this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,   
  19.                 WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  20.         this.requestWindowFeature(Window.FEATURE_NO_TITLE);  
  21.         setContentView(R.layout.main);  
  22.         tv = (TextView) findViewById(R.id.himi_tv);  
  23.         et = (EditText) findViewById(R.id.himi_edit);  
  24.         gov = (GestureOverlayView) findViewById(R.id.himi_gesture);  
  25.         gov.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);//设置笔划类型   
  26.         // GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE 设置支持多笔划  
  27.         // GestureOverlayView.GESTURE_STROKE_TYPE_SINGLE 仅支持单一笔划  
  28.         path = new File(Environment.getExternalStorageDirectory(), "gestures").getAbsolutePath();  
  29.         //得到默认路径和文件名/sdcard/gestures  
  30.         file = new File(path);//实例gestures的文件对象  
  31.         gestureLib = GestureLibraries.fromFile(path);//实例手势仓库  
  32.         gov.addOnGestureListener(new OnGestureListener() { // 这里是绑定手写绘图区  
  33.                     @Override  
  34.                     // 以下方法是你刚开始画手势的时候触发  
  35.                     public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) {  
  36.                         tv.setText("请您在紧凑的时间内用两笔划来完成一个手势!西西~");  
  37.                     }   
  38.                     @Override  
  39.                     // 以下方法是当手势完整形成的时候触发  
  40.                     public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {  
  41.                         gesture = overlay.getGesture();// 从绘图区取出形成的手势  
  42.                         if (gesture.getStrokesCount() == 2) {//我判定当用户用了两笔划  
  43.                             //(强调:如果一开始设置手势笔画类型是单一笔画,那你这里始终得到的只是1!)  
  44.                             if (event.getAction() == MotionEvent.ACTION_UP) {//判定第两笔划离开屏幕  
  45.                                 //if(gesture.getLength()==100){}//这里是判定长度达到100像素  
  46.                                 if (et.getText().toString().equals("")) {  
  47.                                     tv.setText("由于您没有输入手势名称,so~保存失败啦~");  
  48.                                 } else {  
  49.                                     tv.setText("正在保存手势...");  
  50.                                     addGesture(et.getText().toString(), gesture);//我自己写的添加手势函数   
  51.                                 }  
  52.                             }  
  53.                         } else {  
  54.                             tv.setText("请您在紧凑的时间内用两笔划来完成一个手势!西西~");  
  55.                         }  
  56.                     }   
  57.                     @Override  
  58.                     public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) {  
  59.                     }   
  60.                     @Override  
  61.                     public void onGesture(GestureOverlayView overlay, MotionEvent event) {  
  62.                     }  
  63.                 });  
  64.         //----这里是在程序启动的时候进行遍历所有手势!------  
  65.         if (!gestureLib.load()) {  
  66.             tv.setText("Himi提示:手势超过9个我做了删除所有手势的操作,为了界面整洁一些!"  
  67.                     + " 输入法手势练习~(*^__^*)~ 嘻嘻!/n操作介绍:(画手势我设置必须画两笔划才行哦~)/n1." +  
  68.                             "添加手势:先EditText中输入名称,然后在屏幕上画出手势!/n2.匹配手势:"   
  69.                     + "在EditText输入/"himi/",然后输入手势即可! ");  
  70.         } else {  
  71.             Set<String> set = gestureLib.getGestureEntries();//取出所有手势  
  72.             Object ob[] = set.toArray();  
  73.             loadAllGesture(set, ob);  
  74.         }  
  75.     }  

      这个就是MainActivity主要代码了,其中添加手势、匹配手势、遍历手势、将手势转成图片这些我都单独写成了函数,这样让各位童鞋更清晰思路一些。

     从以上代码中我们看出在创建手势之前,手写绘图区(GestureOverlayView)肯定先被创建出来,然后我们就可以在其区域中进行笔划绘画手势了,当然绘画手势前,我们也需要设置了笔划类型,也就是我一开始给大家介绍的~其后最重要的就是手写绘图区的手势监听器绑定,增加OnGestureListener这个监听器重写了四个函数,这里最重要的就两个函数:

onGestureStarted 和 onGestureEnded ; 手势开始和手势结束的监听函数!

    尤其是手势结束监听这个函数尤为重要,在其中我设置好几个条件语句,这么几个条件一方面是让大家了解Gesture中一些比较重要常用的方法,另一方面我要提醒各位童鞋:

    如果你设置笔划类型是多笔划类型的,那么理想状态下,应该是在一段紧凑时间内,不管你使用了几笔划来绘制手势,系统都应该在判定你在一定短暂时间内没有再进行笔划的时候才应该创建手势,并且系统响应此函数;

    其实错了,一开始我也这么想,但是发现,不管你设置的笔划类型是单一的还是多笔划当你手指离开屏幕,不管你当前是第几笔,Android都会去响应这个完成函数,so~ 我在这里调用手势Gesture类中的getStrokesCount()函数,这个函数会记录在紧凑时间内你绘制手势的笔划数,那么根据这个函数我们就可以解决手指离开屏幕总被响应的问题了,因为单一笔划类型永远这个值不会大于1!

    而 if (event.getAction() == MotionEvent.ACTION_UP) {}写这个只是给大家演示第二个参数按键动作该怎么用;

 那么我们下面就来看如何创建一个手势:

 

  
  
  1.     public void addMyGesture(String name, Gesture gesture) {   
  2.         try {  
  3.             if (name.equals("himi")) {  
  4.                 findGesture(gesture);  
  5.             } else {  
  6.                 // 关于两种方式创建模拟器的SDcard在【Android2D游戏开发之十】有详解  
  7.                 if (Environment.getExternalStorageState() != null) {// 这个方法在试探终端是否有sdcard!  
  8.                     if (!file.exists()) {// 判定是否已经存在手势文件  
  9.                         // 不存在文件的时候我们去直接把我们的手势文件存入  
  10.                         gestureLib.addGesture(name, gesture);  
  11.                         if (gestureLib.save()) {////保存到文件中  
  12.                             gov.clear(true);//清除笔画  
  13.                             // 注意保存的路径默认是/sdcard/gesture ,so~别忘记AndroidMainfest.xml加上读写权限!  
  14.                             // 这里抱怨一下,咳咳、其实昨天就应该出这篇博文的,就是因为这里总是异常,今天仔细看了  
  15.                             // 才发现不是没写权限,而是我虽然在AndroidMainfest.xml中写了权限,但是写错了位置..哭死!  
  16.                             tv.setText("保存手势成功!因为不存在手势文件," + "所以第一次保存手势成功会默认先创" +  
  17.                                     "建了一个手势文件!然后将手势保存到文件中.");  
  18.                             et.setText("");  
  19.                             gestureToImage(gesture);  
  20.                         } else {  
  21.                             tv.setText("保存手势失败!");  
  22.                         }  
  23.                     } else {//当存在此文件的时候我们需要先删除此手势然后把新的手势放上  
  24.                         //读取已经存在的文件,得到文件中的所有手势  
  25.                         if (!gestureLib.load()) {//如果读取失败  
  26.                             tv.setText("手势文件读取失败!");  
  27.                         } else {//读取成功   
  28.                             Set<String> set = gestureLib.getGestureEntries();//取出所有手势  
  29.                             Object ob[] = set.toArray();  
  30.                             boolean isHavedGesture = false;  
  31.                             for (int i = 0; i < ob.length; i++) {//这里是遍历所有手势的name   
  32.                                 if (((String) ob[i]).equals(name)) {//和我们新添的手势name做对比  
  33.                                     isHavedGesture = true;  
  34.                                 }  
  35.                             }  
  36.                             if (isHavedGesture) {//如果此变量为true说明有相同name的手势  
  37. //----备注1-------------------//gestureLib.removeGesture(name, gesture);//删除与当前名字相同的手势  
  38. /*----备注2-----------------*/gestureLib.removeEntry(name);  
  39.                                 gestureLib.addGesture(name, gesture);  
  40.                             } else {  
  41.                                 gestureLib.addGesture(name, gesture);  
  42.                             }  
  43.                             if (gestureLib.save()) {  
  44.                                 gov.clear(true);//清除笔画   
  45.                                 gestureToImage(gesture);  
  46.                                 tv.setText("保存手势成功!当前所有手势一共有:" + ob.length + "个");  
  47.                                 et.setText("");  
  48.                             } else {  
  49.                                 tv.setText("保存手势失败!");  
  50.                             }  
  51.                             ////------- --以下代码是当手势超过9个就全部清空 操作--------  
  52.                             if (ob.length > 9) {  
  53.                                 for (int i = 0; i < ob.length; i++) {//这里是遍历删除手势  
  54.                                     gestureLib.removeEntry((String) ob[i]);  
  55.                                 }  
  56.                                 gestureLib.save();  
  57.                                 if (MySurfaceView.vec_bmp != null) {  
  58.                                     MySurfaceView.vec_bmp.removeAllElements();//删除放置手势图的容器  
  59.                                 }  
  60.                                 tv.setText("手势超过9个,已全部清空!");  
  61.                                 et.setText("");  
  62.                             }  
  63.                             ob = null;  
  64.                             set = null;  
  65.                         }  
  66.                     }  
  67.                 } else {  
  68.                     tv.setText("当前模拟器没有SD卡 - -。");  
  69.                 }  
  70.             }  
  71.         } catch (Exception e) {  
  72.             tv.setText("操作异常!");  
  73.         }  
  74.     } 

 

     这里也都很好理解,套路类似之前File文件存储的套路,先判断SD是否存在,然后是文件是否存在:

    如果文件不存在就先直接添加到手势到手势仓库中,然后手势仓调用gestureLib.save()才算把手势存到SD卡的手势文件中。

    文件存在的话还要去判定是否文件中包含了相同名字的手势;当然这里可以不判定是否有相同手势名存在,然后进行删除操作!其实也可不删除,直接添加进去当前新建的手势;原因看了下面的备注解释就明白了;

     备注 1:因为gestureLib保存的手势是个HashMap, key=手势的名字,value=手势,所以gestureLib.removeGesture(name, gesture);这种删除方式只是删除了手势,该手势名字依旧保存在hashmap中,下次还有相同的name手势存入的时候Hashmap就直接覆盖本条目了。所以根据Hashmap的特征,我们可以不进行删除操作,可以直接gestureLib.addGesture(name, gesture);因为如果出现相同的手势名字的手势,Hashmap就会根据key(手势的名字)直接覆盖其条目的value(手势)滴~

    备注2 :这里也是一种删除手势的方式,但是这种方式跟备注1的不同,这里是将Hashmap中的条目删除,也就是说key和value都被删去!

 下面看下如何把手势转成bitmap!

 

  
  
  1. public void gestureToImage(Gesture ges) {//将手势转换成Bitmap  
  2.         //把手势转成图片,存到我们SurfaceView中定义的Image容器中,然后都画出来~  
  3.         if (MySurfaceView.vec_bmp != null) {  
  4.             MySurfaceView.vec_bmp.addElement(ges.toBitmap(100, 100, 12, Color.GREEN));  
  5.         }  
  6.     } 

 

下面是如何遍历手势! 


   
   
  1. public void loadAllGesture(Set<String> set, Object ob[]) { //遍历所有的手势   
  2.         if (gestureLib.load()) {//读取最新的手势文件  
  3.             set = gestureLib.getGestureEntries();//取出所有手势  
  4.             ob = set.toArray();  
  5.             for (int i = 0; i < ob.length; i++) {  
  6.                 //把手势转成Bitmap  
  7.                 gestureToImage(gestureLib.getGestures((String) ob[i]).get(0));  
  8.                 //这里是把我们每个手势的名字也保存下来  
  9.                 MySurfaceView.vec_string.addElement((String) ob[i]);  
  10.             }  
  11.         }  
  12.     } 
  下面最后来看看手势的匹配!(超重要的!自己也搞了许久才找到解决的方法)
 

   
   
  1. public void findGesture(Gesture gesture) {  
  2.     try {  
  3.         // 关于两种方式创建模拟器的SDcard在【Android2D游戏开发之十】有详解  
  4.         if (Environment.getExternalStorageState() != null) {// 这个方法在试探终端是否有sdcard!  
  5.             if (!file.exists()) {// 判定是否已经存在手势文件  
  6.                 tv.setText("匹配手势失败,因为手势文件不存在!!");  
  7.             } else {//当存在此文件的时候我们需要先删除此手势然后把新的手势放上  
  8.                 //读取已经存在的文件,得到文件中的所有手势  
  9.                 if (!gestureLib.load()) {//如果读取失败  
  10.                     tv.setText("匹配手势失败,手势文件读取失败!");  
  11.                 } else {//读取成功   
  12.                     List<Prediction> predictions = gestureLib.recognize(gesture);  
  13.                     //recognize()的返回结果是一个prediction集合,  
  14.                     //包含了所有与gesture相匹配的结果。  
  15.                     //从手势库中查询匹配的内容,匹配的结果可能包括多个相似的结果,   
  16.                     if (!predictions.isEmpty()) {  
  17.                         Prediction prediction = predictions.get(0);  
  18.                         //prediction的score属性代表了与手势的相似程度  
  19.                         //prediction的name代表手势对应的名称   
  20.                         //prediction的score属性代表了与gesture得相似程度(通常情况下不考虑score小于1的结果)。   
  21.                         if (prediction.score >= 1) {  
  22.                             tv.setText("当前你的手势在手势库中找到最相似的手势:name =" + prediction.name);  
  23.                         }  
  24.                     }  
  25.                 }  
  26.             }  
  27.         } else {  
  28.             tv.setText("匹配手势失败,,当前模拟器没有SD卡 - -。");  
  29.         }  
  30.     } catch (Exception e) {  
  31.         e.printStackTrace();  
  32.         tv.setText("由于出现异常,匹配手势失败啦~");  
  33.     }  

     那么最后给各位童鞋说一下,其实输入法手势操作很是适合游戏中使用,不管是触摸屏手势操作还是今天讲的输入法手势操作如果加到游戏中那都是相当赞的!但是我们公司网游引擎和框架不适合插入手势 - -、唉~

    其实前两天应该发这篇的,但是因为工作忙了几天,让大家久等了,挺不好意思的,所以今天熬夜给大家写了出来,现在都凌晨 7:00 了~

 源码下载地址: http://www.himigame.com/android-game/340.html










本文转自 xiaominghimi 51CTO博客,原文链接:http://blog.51cto.com/xiaominghimi/606792,如需转载请自行联系原作者
目录
相关文章
|
3月前
|
缓存 前端开发 Android开发
安卓开发中的自定义视图:从零到英雄
【10月更文挑战第42天】 在安卓的世界里,自定义视图是一块画布,让开发者能够绘制出独一无二的界面体验。本文将带你走进自定义视图的大门,通过深入浅出的方式,让你从零基础到能够独立设计并实现复杂的自定义组件。我们将探索自定义视图的核心概念、实现步骤,以及如何优化你的视图以提高性能和兼容性。准备好了吗?让我们开始这段创造性的旅程吧!
55 1
|
4月前
|
Android开发 开发者
安卓应用开发中的自定义视图
【9月更文挑战第37天】在安卓开发的海洋中,自定义视图犹如一座座小岛,等待着勇敢的探索者去发现其独特之处。本文将带领你踏上这段旅程,从浅滩走向深海,逐步揭开自定义视图的神秘面纱。
53 3
|
6月前
|
存储 Shell Android开发
基于Android P,自定义Android开机动画的方法
本文详细介绍了基于Android P系统自定义开机动画的步骤,包括动画文件结构、脚本编写、ZIP打包方法以及如何将自定义动画集成到AOSP源码中。
131 2
基于Android P,自定义Android开机动画的方法
|
4月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
151 0
|
6月前
|
供应链 物联网 区块链
未来触手可及:探索新兴技术的趋势与应用安卓开发中的自定义视图:从基础到进阶
【8月更文挑战第30天】随着科技的飞速发展,新兴技术如区块链、物联网和虚拟现实正在重塑我们的世界。本文将深入探讨这些技术的发展趋势和应用场景,带你领略未来的可能性。
|
6月前
|
测试技术 Android开发 Python
探索软件测试的艺术:从基础到高级安卓应用开发中的自定义视图
【8月更文挑战第29天】在软件开发的世界中,测试是不可或缺的一环。它如同艺术一般,需要精细的技巧和深厚的知识。本文旨在通过浅显易懂的语言,引领读者从软件测试的基础出发,逐步深入到更复杂的测试策略和工具的使用,最终达到能够独立进行高效测试的水平。我们将一起探索如何通过不同的测试方法来确保软件的质量和性能,就像艺术家通过不同的色彩和笔触来完成一幅画作一样。
|
3月前
|
Java API 开发工具
Cocos游戏如何快速接入安卓优量汇广告变现?
本文介绍了如何在Cocos游戏项目中快速接入安卓优量汇广告,通过详细的步骤指导,包括前期准备、编辑gradle和清单文件、核心代码集成等,帮助开发者轻松实现广告功能,增加游戏的盈利渠道。文中还提供了示例工程下载链接,方便开发者直接上手实践。
|
3月前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
3月前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
68 5
|
4月前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 3
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 4
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 5
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 6
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 7
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 8
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 9
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 10
    Android学习自定义View(四)——继承控件(滑动时ListView的Item出现删除按钮)