精华内容
下载资源
问答
  • android开发思路、一些想法

    千次阅读 2016-04-15 09:39:28
    Android系统一开始并不是由谷歌研发出来了,Android系统原来的公司名字就叫做Android,谷歌公司在2005收购了这个仅成立22月的高科技企业。...这些功能通过Android应用框架暴露给开发人员. Android Runtime (Android


    手机客户端直接操作服务器端的数据库。读取数据。要考虑中间有多少个流程?


    文字数据与图片数据的获取与处理:json数据;

    文字信息可以直接从服务器端的返回数据直接获得,但是图片数据从服务器端返回的是是图片地址。

    数据库的话本地是内嵌的sqlite,服务器端就是web上的Mysql

    是否需要服务端支持(远程服务器、服务器端获取数据),是否需要本地数据库支持(本地数据库)?

    先说Android 设计思路
    1. 根据需求设计数据库 ,因为 几乎所有操作都要参考数据模型 。日访问  1w  / 次以下用 sqlserver  或者 mysql  就行。
    2. 其次设计 android  端界面,界面设计好,业务逻辑基本就能想连贯了。
    3. 再次完成 android  实体类的建立和功能实现
    4. 最后再返回服务器端设计处理,手机端发送来的请求,使用框架编写服务器端后台使用 struts2  控制处理请求

    大致就以上四个步骤。

    确定功能----->架构设计------>界面设计------>数据操作和存储------>业务实现------>页面跳转


    嵌入式系统:用在一些特定专用设备上,通常这些设备的硬件资源(如处理器、存储器等)非常有限,并且对成本很敏感,有时对实时响应要求很高等。特别是随着消费家电的智能化,嵌入式更显重要。嵌入式系统是软硬结合的东西,搞嵌入式开发的人有两类。

    一类是学电子工程、通信工程等偏硬件专业出身的人,他们主要是搞硬件设计,有时要开发一些与硬件关系最密切的最底层件BootLoaderBoard Support Package(像PCBIOS一样,往下驱动硬件,往上支持操作系统),最初级的硬件驱动程序等。他们的优势是对硬件原理非常清楚,他们更擅长定义各种硬件接口,但对复杂软件系统往往力不从心(例如嵌入式操作系统原理和复杂应用软件等)。

    (清楚硬件原理,擅长定义各种硬件接口,不善于开发复杂的软件应用,硬件驱动程序)

    另一类是学软件、计算机专业出身的人,主要从事嵌入式操作系统和应用软件的开发。学软件的人对硬件原理和接口通常难以有较好的掌握,最多也只能写部分BSP硬件驱动程序。嵌入式硬件设计完后,各种功能就全靠软件来实现了,嵌入式设备的增值很大程度上取决于嵌入式软件,稍复杂的硬件都交给台湾或国外公司设计,国内的硬件设计力量很弱,很多嵌入式公司自己只负责开发软件,因为公司都知道,嵌入式产品的差异很大程度在软件上,在软件方面是最有花头可做的),所以搞软件的人完全不用担心自己在嵌入式市场上的用武之地,越是智能设备越是复杂系统,软件越起关键作用。

    ————————————————————————————————————————>

    Android系统一开始并不是由谷歌研发出来了,Android系统原来的公司名字就叫做Android谷歌公司在2005收购了这个仅成立22的高科技企业。

     

    Android体系结构

    Libraries (): Android包含一套C/C++库,Android系统的各式组件都在使用。这些功能通过Android应用框架暴露给开发人员.

    Android Runtime (Android运行时) 每个Android应用都运行在自己的进程上,享有Dalvik虚拟机为它分配的专有实例。为了支持多个虚拟机在同一个设备上高效运行,Dalvik被改写过。 

    Applications (应用Android预装一组核心应用程序,包括E-mail客户端、短信服务、日历日程、地图服务、浏览器、联系人和其他应用程序。所有应用程序都是Java编程语言编写的。 

     

    Android开发四大组件分别是:

    活动(Activity): 用于表现功能

    服务(Service): 后台运行服务,不提供界面呈现。

    广播接收器(BroadcastReceiver):用于接收广播,是一种消息机制。

    内容提供商(Content Provider):支持在多个应用中存储和读取数据,相当于数据库;操作短信数据库

     

    Android 中,Activity是所有程序的根本,所有程序的流程都运行在Activity 之中,在Android的程序当中,Activity 一般代表手机屏幕的一屏。如果把手机比作一个浏览器,那么Activity就相当于一个网页。在Activity 当中可以添加一些ButtonCheck box 等控件。可以看到Activity 概念和网页的概念相当类似.

     

    安全权限机制

    Android安全架构的核心设计思想是,在默认设置下,所有应用都没有权限对其他应用、系统或用户进行较大影响的操作。这其中包括读写用户隐私数据(联系人或电子邮件),读写其他应用文件,访问网络或阻止设备待机等。


    Android 应用程序权限申请 :每个应用程序的 APK 包里面都包含有一个 AndroidMainifest.xml 文件,该文件除了罗列应用程序运行时库、运行依赖关系等之外,还会详细地罗列出该应用程序所需的系统访问权限。程序员在进行应用软件开发时,需要通过设置该文件的 uses-permission 字段来显式地向 Android 系统申请访问权限。用户安装的时候可以分析一款应用所需权限,从而简单判定这款应用是否安全。

     

     

    Android系统特性

    源代码完全开放

    手机、PDAGPSMIDMP4NB等众多设备均可以安装该系统

    内置Google独特业务、工具(搜索,导航,GmailGoogle Talk,语音搜索)

    未来Google云计算技术

    更好的硬件层调用GPS模块,Wifi模块,重力感应,3D加速)(操作硬件

    可以使用JAVA基于Android SDK开发上层应用、游戏。也可以使用C++基于Android NDK开发底层和对效率要求较高的核心算法

     

    Android的优势

    网络集成性很高

    Android内部集成了大量的google应用,如GmailReaderMapDocsYoutube等等,涵盖了生活中各个方面的网络应用,对长期使用网络、信息依赖度比较高的人群很合适。

    Android具备创新性

    自从Google开发出Android后,许多人认为其技术可信度要比其它操作系统略胜一筹,但这并不是用户购买Android智能手机的唯一原因。人们认为Android一种相对较新的、又较为成熟的技术,在达到巅峰之前还有很大发展空间。

    Android平台在数量上逐渐主宰市场

    Android在其它领域的拓展

    Android不仅促进了手机产业的发展,它的全面计算服务和丰富的功能支持,已将应用拓展到手机以外的其他领域。Android平台的通用性可以适用于不同的屏幕、有线和无线设备。

     

    常见的智能手机操作系统

    android(谷歌)  ios(苹果)  wp(微软)黑莓(rim) bada(三星)oms(移动)

     

    移动互联网

    就是将移动通信和互联网二者结合起来,成为一体。移动通信和互联网成为当今世界发展最快、市场潜力最大、前景最诱人的两大业务,它们的增长速度都是任何预测家未曾预料到的,所以移动互联网可以预见将会创造经济神话。

     

    移动互联网十大业务模式

    移动社交将成客户数字化生存的平台

    移动广告将是移动互联网的主要盈利来源

    手机游戏将成为娱乐化先锋

    手机电视将成为时尚人士新宠

    移动电子阅读填补狭缝时间

    移动定位服务提供个性化信息

    手机搜索将成为移动互联网发展的助推器

    手机内容共享服务将成为客户的黏合剂

    移动支付蕴藏巨大商机

    移动电子商务的春天即将到来

     

    Android开发者收入顺序

    1)移动广告,2)付费下载,3)虚拟货币,4)应用内购买。

    移动广告的优势在于定位。据调研机构的报告,位置相关的广告能够有效提高广告点击率;

    移动广告具备精准性、互动性、灵活性和个性化的特点,同时更关注随身性、便捷性、用户收看场景和网络承载力等因素。

    展开全文
  • Android开发效率改进思路
  • Android音视频开发学习思路
  • 一个简要的android平台下游戏开发思路
  • android手游屏幕自适应开发思路
  • 下拉刷新效果功能在程序开发中经常会见到,今天小编抽时间给大家分享Android开发之无痕过渡下拉刷新控件的实现思路详解,需要的朋友参考下吧
  • Android 音视频开发学习思路

    千次阅读 2017-08-30 13:02:00
    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的。只能通过一点点的学习和积累把这块的知识串联积累起来。 初级入门篇: Android 音视频开发(一) : 通过三种方式绘制...

    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的。只能通过一点点的学习和积累把这块的知识串联积累起来。

    初级入门篇:

    初级入门篇主要是接触Android多媒体展示相关的API,通过单独的列举和使用这些API,对Android音视频处理有一个基本的轮廓,虽然知识点相对来说是比较散的,但是点成线,线称面,基本的基础掌握了,通过学习Android音视频核心的API将音视频的流程串联起来,这样对于音视频的了解和控制就不仅仅局限于最外层的API了,而是能够通过相对底层的方式来加深对Android 音视频开发的认知。 

    中级进阶篇:

    OpenGL ES 学习记录

    学习 Android 平台 OpenGL ES API,了解 OpenGL 开发的基本流程,使用 OpenGL 绘制基本图形,并了解相关的API的简单使用

    动手实践,积累实战经验:

    个人学习成果展示:

    OpenSL ES 学习记录

    学习 Android 平台 OpenSL ES API,了解 OpenSL 开发的基本流程,使用OpenSL播放PCM数据,并了解相关API的简单使用

    高级探究篇:

    • 深入研究音视频相关的网络协议,如 rtmp,hls,以及封包格式,如:flv,mp4
    • 深入学习一些音视频领域的开源项目,如 webrtc,ffmpeg,ijkplayer,librtmp 等等
    • 将 ffmpeg 库移植到 Android 平台,结合上面积累的经验,编写一款简易的音视频播放器
    • 将 x264 库移植到 Android 平台,结合上面积累的经验,完成视频数据 H264 软编功能
    • 将 librtmp 库移植到 Android 平台,结合上面积累的经验,完成 Android RTMP 推流功能 

    FFmpeg 学习记录

    FFmpeg 结构体学习

    音视频开发开源库

    GPUImageIjkPlayerlibrestreamingRTMPDumpSoundTouch

    学习展望

      完成上面的学习后,可以尝试做一款音视频相关的APP,这个APP尽可能多的用上你学习的知识,看看能做到什么程度。如果你能很好的做出来,并认真的把上面列举的所有的点都完成和整理了,相信你在Android音视频领域会越走越好。

    推荐的学习资料:

        1. 《雷霄骅的专栏》:http://blog.csdn.net/leixiaohua1020

        2. 《Android音频开发》:http://ticktick.blog.51cto.com/823160/d-15

        3. 《FFMPEG Tips》:http://ticktick.blog.51cto.com/823160/d-17

        4. 《Learn OpenGL 中文》:https://learnopengl-cn.github.io/

        5. 《Android Graphic 架构》:https://source.android.com/devices/graphics/

        6. 《Jhuster的专栏》:http://blog.51cto.com/ticktick

        7. 《ywl5320的专栏》:https://blog.csdn.net/ywl5320

    展开全文
  • 假如我设计一个类似贴吧的app,不需要登陆也能浏览帖子,但是有些功能,比如回复,则需要检测是否登陆。这样的业务逻辑用什么来做比较方便?
  • android studio游戏摇杆开发教程,仿王者荣耀摇杆

    万次阅读 多人点赞 2018-06-16 02:48:42
    经过几天的思考已完美解决所有问题,下面就和大家分享下这个摇杆的开发思路(此教程不包含游戏源码) 若有不正之处,请多多谅解并欢迎指正。 首先这个摇杆要用到较多的数学知识,小编的数学特别烂也就高中水平吧 ...

    李子果 原创。。。

    最近在做一个山寨版的王者荣耀,刚开始做的时候毫无头绪 摇杆的多点触控做的特别烂

    经过几天的思考已完美解决所有问题,下面就和大家分享下这个摇杆的开发思路(此教程不包含游戏源码)

    若有不正之处,请多多谅解并欢迎指正。

    首先这个摇杆要用到较多的数学知识,小编的数学特别烂也就高中水平吧

    我们这个摇杆一共就五个按钮,一个移动摇杆、三个技能摇杆和一个普通攻击按钮

    最终效果

    好了废话少说让我们开始吧

    新建一个项目

    建好项目之后,我们先新建一个类叫做“画”。也是我们的主View

    修改Hua.java的代码

    public class Hua extends RelativeLayout implements Runnable{ //继承RelativeLayout 实现Runnable接口
    
        private Paint p;//画笔
    
        public Hua(Context context) {
            super(context);
            p=new Paint();
            setBackgroundColor(Color.BLACK);//背景颜色设为黑色
        }
    
        @Override
        protected void onDraw(Canvas g) {//重写onDraw方法
            super.onDraw(g);
        }
    
        @Override
        public void run() {
    
        }
    }

    接下来我们做移动摇杆

     

    我们要准备一张图片(待会我会把图片都丢在附件里)

     

    首先用ps画一个这样半透明的圆ps部分就不做教程了

    把背景隐藏掉 保存为png格式

     

    把我们刚刚制作的图片添加进来

    先新建一个类 my.java

    public class my { //这个类当一个全局变量使用
        public static int w,h;//屏幕的宽高
        public static float bili;
        public static MainActivity main;
        public static RectF re=new RectF();
        public static int ontouchAlpha=100;//触控区透明度0-255 0为透明,为了测试我们先设为100
    }

    修改 MainActivity 的代码

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            my.main=this;
            getSupportActionBar().hide();//隐藏标题栏
            this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏 隐藏状态栏
            //判断当前是否横屏 如果不是就设为横屏,设为横屏之后会自动调用onCreate方法
            if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
                //获取屏幕的宽高
                DisplayMetrics dis = getResources().getDisplayMetrics();
                my.w = dis.widthPixels;
                my.h = dis.heightPixels;
                //获取屏幕分辨率和1920*1080的比例 以便适应不同大小的屏幕
                my.bili = (float) (Math.sqrt(my.w * my.h) / Math.sqrt(1920 * 1080));
                setContentView(new Hua(this));
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);// 横屏
            }
        }
    }

    新建类 Move.java

    package com.yaogan.liziguo.yaogan;
    
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    
    /**
     * Created by Liziguo on 2018/6/15.
     */
    
    public class Move {
        private float x1,y1;//按下时的坐标 大圆
        private float x2,y2;//移动后的坐标 小圆
        private final float r1,r2;//r1大圆的半径 r2小圆的半径
        public float angle;//x1y1指向x2y2的角度 弧度制
        public boolean down=false;//判断是否被按下
        public boolean in=false;//判断小圆是否在大圆里面,简单的说就是防止小圆被脱太远
        public boolean move=false;//判断手指按下后是否移动(MY实际开发中用到,该教程用不到此变量)
        public Bitmap img;//大圆小圆的图片
    
        public Move(){
            r1 = 480 * 0.5f * my.bili;//乘上一个比例 适应不同大小的屏幕
            r2 = 300 * 0.5f * my.bili;
            img= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.yaogan);//初始化摇杆图片
        }
    
        public void down(float xx,float yy){ //摇杆按下后的操作
            if(xx<r1) x1=r1;
            else x1 = xx;
    
            if(my.h-yy<r1) y1=my.h-r1;
            else y1 = yy;
            //上面的代码是防止按下的位置太靠近屏幕边缘
            //跟x1=xx;y1=yy;区别不大,待会可以改成x1=xx;y1=yy;看看效果有什么不同
            down=true;
        }
        public void move(float xx,float yy){ //按下摇杆后移动的操作
            angle=getAngle(xx,yy);
            in=in(xx, yy);
            move=isMove(xx,yy);
            if (!in) {
                //下面会做解释
                xx= (float) (x1+ Math.sin(angle)*r1*0.7f);
                yy= (float) (y1+ Math.cos(angle)*r1*0.7f);
            }
            x2=xx;
            y2=yy;
        }
        public void up(){ //松开后的操作
            down=false;
        }
    
        public float getAngle(float xx,float yy){ //获取x1y1指向x2y2的角度
            double angle,k;
            if (y1==yy)//斜率不存在时
                if (x1 > xx)//判断x1指向x2的方向
                    angle=-Math.PI/2;
                else
                    angle=Math.PI/2;
            else{
                k=(x1-xx)/(y1-yy); //两点的坐标求斜率,至于为什么是(x1-x2)/(y1-y2)不是(y1-y2)/(x1-x2)待会我们再做解释
                if (y1 > yy) {//判断x1y1指向x2y2的方向
                    // 用反tan求角度 这个高中好像没学过 既然Math类已经帮我们封装好了就直接拿来用吧
                    angle=Math.atan(k) + Math.PI;
                } else {
                    angle=Math.atan(k);
                }
                //这段可写可不写 让计算出来的角度属于-PI/2到PI/2
                if(angle>Math.PI)
                    angle-=Math.PI*2;
                else if(angle<-Math.PI)
                    angle+=Math.PI*2;
            }
            return (float) angle;
        }
    
        public boolean in(float xx, float yy) { //防止小圆被脱太远 拖动范围不超出r1的70%
            double r = Math.sqrt((x1 - xx) * (x1 - xx) + (y1 - yy) * (y1 - yy));//两点间距离公式
            if (r < r1*0.7f)
                return true;
            else return false;
        }
        public boolean isMove(float xx, float yy) { //判断按下摇杆后 是否移动,如果x1y1 x2y2的距离大于r1*0.15视为移动
            // MY实际开发中用到,该教程用不到此变量
            double r = Math.sqrt((x1 - xx) * (x1 - xx) + (y1 - yy) * (y1 - yy));//两点间距离公式
            if (r > r1*0.15f)
                return true;
            else return false;
        }
        public void onDraw(Canvas g, Paint p){ //画摇杆
            if(down) { //当摇杆被按下时 才显示
                //怎么用Canvas画图这里就不说了
                my.re.left = x1 - r1;
                my.re.top = y1 - r1;
                my.re.right = x1 + r1;
                my.re.bottom = y1 + r1;
                g.drawBitmap(img, null, my.re, p); //画大圆
                my.re.left = x2 - r2;
                my.re.top = y2 - r2;
                my.re.right = x2 + r2;
                my.re.bottom = y2 + r2;
                g.drawBitmap(img, null, my.re, p); //画小圆
            }
        }
    }

    新建类 OnTouchMove.java 

    package com.yaogan.liziguo.yaogan;
    
    import android.content.Context;
    import android.graphics.Color;
    import android.view.MotionEvent;
    import android.view.View;
    
    /**
     * Created by Liziguo on 2018/6/16.
     */
    
    public class OnTouchMove extends View { //这个view负责监听移动摇杆的手势
        
        private Move m;
        
        public OnTouchMove(Context context,Move move) {
            super(context);
            this.m=move;
            setBackgroundColor(Color.WHITE);//背景色设为白色
            getBackground().setAlpha(my.ontouchAlpha);//设置触控区透明度
            setOnTouchListener(new OnTouchListener() { //设置触控监听
                @Override
                public boolean onTouch(View v, MotionEvent ev) {
                    //加上getX() getY()因为这个view不是分布在左上角的
                    final float xx = ev.getX() + getX(), yy = ev.getY() + getY();
    
                    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
                        m.down(xx, yy);//按下时的操作
    //                    m.move(xx, yy);
                    }
                    m.move(xx, yy);//移动时的操作
                    if (ev.getAction() == MotionEvent.ACTION_UP) {
                        m.up();//松开时的操作
                    }
                    return true;//不要返回false
                }
            });
        }
    }

    修改 Hua.java 的代码

    package com.yaogan.liziguo.yaogan;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.widget.RelativeLayout;
    
    /**
     * Created by Liziguo on 2018/6/15.
     */
    
    public class Hua extends RelativeLayout implements Runnable{ //继承RelativeLayout 实现Runnable接口
    
        private Paint p;//画笔
        private Move m=new Move();//移动摇杆
    
        public Hua(Context context) {
            super(context);
            p=new Paint();
            setBackgroundColor(Color.BLACK);//背景颜色设为黑色
            //实例化一个OnTouchMove
            OnTouchMove onTouchMove=new OnTouchMove(context,m);
            //把onTouchMove添加进来 宽度为屏幕的1/3 高度为屏幕的1/2
            addView(onTouchMove,my.w/3,my.h/2);
            //设置onTouchMove的位置
            onTouchMove.setX(0);
            onTouchMove.setY(my.h/2);
    
            new Thread(this).start();//启动重绘线程
        }
    
        @Override
        protected void onDraw(Canvas g) {//重写onDraw方法
            super.onDraw(g);
            m.onDraw(g,p);//画移动摇杆
        }
    
        @Override
        public void run() { //每隔20毫秒刷新一次画布
            while(true){
                try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}
                postInvalidate();//重绘 在子线程重绘不能调用Invalidate()方法
            }
        }
    }

    好的 现在我们的摇杆可以说已经做好一大半了,因为剩下的原理都一样

    先运行一遍看看效果吧

    左下角的白色矩形是我们的OnTouchMove类,为了更好的测试我们先让他显示出来 等做好了再隐藏掉

    下面我们来解释一下为什么斜率k=(x1-x2)/(y1-y2)而不是(y1-y2)/(x1-x2)吧

    因为我们手机上的平面直角坐标系跟数学上的平面直角坐标系不一样

    数学上的平面直角坐标系是这样的

    而我们手机是这样的

    有没有发现把手机的坐标系 逆时针旋转一下就是数学里的坐标系了,不过x跟y调了一下位置

    所以我们在写代码的时候把x y换一下就行了

    数学坐标系中k=1的直线

    程序中k=1的直线

    再解释下 Move 类的 move方法

     

    public void move(float xx,float yy){ //按下摇杆后移动的操作
            angle=getAngle(xx,yy);
            in=in(xx, yy);
            move=isMove(xx,yy);
            if (!in) {
                //下面会做解释
                xx= (float) (x1+ Math.sin(angle)*r1*0.7f);
                yy= (float) (y1+ Math.cos(angle)*r1*0.7f);
            }
            x2=xx;
            y2=yy;
        }

     

    不知不觉已经凌晨2:46了,今天就写到这吧

     

    明天继续。。。。。。

     

    好的下面我们开始做技能摇杆,这教程做的比较累啊

    下面的技能类是我直接从我游戏里拷贝过来的并做了些小修改

    解释可能没那么清楚毕竟原理都一样

    只不过是多了几个功能而已

     

    准备图片

     

    添加到工程里

    由于图片比较多 我们加载图的代码位置改一下

    修改 MainActivity。java 和 my.java

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            my.main=this;
            getSupportActionBar().hide();//隐藏标题栏
            this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏 隐藏状态栏
            //判断当前是否横屏 如果不是就设为横屏,设为横屏之后会自动调用onCreate方法
            if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
                //获取屏幕的宽高
                DisplayMetrics dis = getResources().getDisplayMetrics();
                my.w = dis.widthPixels;
                my.h = dis.heightPixels;
                //获取屏幕分辨率和1920*1080的比例 以便适应不同大小的屏幕
                my.bili = (float) (Math.sqrt(my.w * my.h) / Math.sqrt(1920 * 1080));
                //加载图片
                my.border= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.border);
                my.cancel= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.cancel);
                my.down= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.down);
                my.yaogan= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.yaogan);
                my.cd= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.cd);
                setContentView(new Hua(this));
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);// 横屏
            }
        }
    }
    public class my { //这个类当一个全局变量使用
        public static int w,h;//屏幕的宽高
        public static float bili;
        public static MainActivity main;
        public static RectF re=new RectF();
        public static int ontouchAlpha=100;//触控区透明度0-255 0为透明,为了测试我们先设为100
    
        public static Bitmap border,cancel,down,yaogan,cd;
    
        public static Skill skill;//当前正在使用的技能 现在会报错 因为我们还没新建技能Skill类
    }

    修改 Move 类的构造方法

        public Move(){
            r1 = 480 * 0.5f * my.bili;//乘上一个比例 适应不同大小的屏幕
            r2 = 300 * 0.5f * my.bili;
    //      img= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.yaogan);//初始化摇杆图片
            img=my.yaogan;
        }

     

     

    新建技能类 Skill.java

     

     

    package com.yaogan.liziguo.yaogan;
    
    import android.graphics.Bitmap;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    
    /**
     * Created by Liziguo on 2018/6/16.
     */
    
    public abstract class Skill {
        public int jineng;
        private final float x,y;//技能图标中心位置,不是按下时的位置
        private float x2, y2;//技能按下移动后手指的坐标
        private float xxx,yyy;//判断拖动点是否超出两倍r的范围
        private final float calcelx, cancely;
        public float angle;//技能按下后 x y指向xx yy的角度
        public Bitmap img, imgborder, imgdown, imgyaogan,imgcd,imgcancel;
        private final float r2;
        private final float r3=50*my.bili;
        public boolean down=false;
        public boolean down_main=false;//down_main 只触发一次;
        public boolean cancel=false;
        public int cdmax;
        public long last,cd=0;//last最后一次释放技能的时间
        /*
        0 普通攻击
        1 技能1
        2 技能2
        3 技能3
         */
        public Skill(int jineng, int cd, Bitmap image){
            this.jineng=jineng;
            switch (jineng){
                case 0:
                    x= my.w*0.87f;
                    y= my.h*0.8f;
                    break;
                case 1:
                    x= my.w*0.7f;
                    y= my.h*0.88f;
                    break;
                case 2:
                    x= my.w*0.75f;
                    y= my.h*0.62f;
                    break;
                case 3:
                    x= my.w*0.9f;
                    y= my.h*0.5f;
                    break;
                default:x=y=0;
            }
            cdmax=cd;
            if(jineng == 0) r2=125*my.bili;
            else r2=80*my.bili;
            calcelx =my.w-r2*2;
            cancely =my.h/4;
            img=image;
            imgborder=my.border;
            imgdown=my.down;
            imgyaogan=my.yaogan;
            imgcd=my.cd;
            imgcancel=my.cancel;
        }
        //    public abstract void down();
    //    public abstract void move();
    //    public abstract void up();
        public void down(){ //DOWN 由ontouch触发
            if(cd>0)return;
            down=true;
            my.skill=this;
        }
        public abstract void down_main(); //DOWN 教程用不到该抽象方法
    
        public void move(float x,float y){//按下技能后 由ontouch触发
            x2 =x;
            y2 =y;
            angle=getAngle(x2, y2);
            cancel=incancel(x,y);
            if (jineng !=0 && !in2(x,y)) {
                xxx= (float) (this.x+ Math.sin(angle)*r2*2);
                yyy= (float) (this.y+ Math.cos(angle)*r2*2);
            }else{
                xxx=x;
                yyy=y;
            }
        }
        public abstract void move_main();//按下技能后 由MyActor触发 教程用不到该抽象方法
        public abstract void up(); //松开后 由MyActor触发 释放技能
    
        public boolean in(float xx,float yy){ //判断是否被点中
            double r= Math.sqrt((x - xx)*(x-xx)+(y-yy)*(y-yy));
            if(r<r2)
                return true;
            else return false;
        }
        public boolean in2(float xx, float yy) { //判断拖动点是否超出两倍r的范围
            double r = Math.sqrt((x - xx) * (x - xx) + (y - yy) * (y - yy));
            if (r < r2 * 2)
                return true;
            else return false;
        }
        public boolean incancel(float xx,float yy){ //判断是否取消
            double r= Math.sqrt((calcelx - xx)*(calcelx -xx)+(cancely -yy)*(cancely -yy));
            if(r<r2)
                return true;
            else return false;
        }
        public float getAngle(float xx,float yy){ //x y指向xx yy的角度
            float angle,k;
            if (y==yy)
                if (x > xx)
                    angle= (float) (-Math.PI/2);
                else
                    angle= (float) (Math.PI/2);
            else{
                k=(x-xx)/(y-yy);
                if (y > yy) {
                    angle= (float) (Math.atan(k) + Math.PI);
                } else {
                    angle= (float) Math.atan(k);
                }
                if(angle>Math.PI)
                    angle-=Math.PI*2;
                else if(angle<-Math.PI)
                    angle+=Math.PI*2;
    
            }
            return angle;
        }
        private float drawpx=10*my.bili;
    
        public void next(){
            //计算技能冷却时间
            cd=cdmax-System.currentTimeMillis()+last;
        }
        //按下的时候技能图标下移 显示蓝色框框
        public void onDraw(Canvas g, Paint p){
            my.re.left=x-r2;
            my.re.top=y-r2;
            my.re.right=x+r2;
            my.re.bottom=y+r2;
            if(down){
    //            new RectF(x-r2,y-r2,x+r2,y+r2);
    //            new RectF(x-r2,y-r2+10*my.bili,x+r2,y+r2+10*my.bili);
    //            my.re.left=x-r2;
    //            my.re.top=y-r2;
    //            my.re.right=x+r2;
    //            my.re.bottom=y+r2;
                if(jineng!=0){
                    final float bl=2;
                    my.re.left=x-r2*bl;
                    my.re.top=y-r2*bl;
                    my.re.right=x+r2*bl;
                    my.re.bottom=y+r2*bl;
                    //蓝色框框未下移
                    g.drawBitmap(imgdown,null,my.re,p);
                }
                my.re.left=x-r2;
                my.re.top=y-r2;
                my.re.right=x+r2;
                my.re.bottom=y+r2;
                ///
                //技能图片和技能边框下移
                my.re.top+=drawpx;
                my.re.bottom+=drawpx;
                g.drawBitmap(img,null,my.re,p);
                my.re.left-=drawpx;
                my.re.top-=drawpx;
                my.re.right+=drawpx;
                my.re.bottom+=drawpx;
    
                g.drawBitmap(imgborder,null,my.re,p);
                if(jineng!=0){
                    my.re.left=xxx-r3;
                    my.re.top=yyy-r3;
                    my.re.right=xxx+r3;
                    my.re.bottom=yyy+r3;
                    g.drawBitmap(imgyaogan,null,my.re,p);
                    //cancle
                    my.re.left= calcelx -r2;
                    my.re.top= cancely -r2;
                    my.re.right= calcelx +r2;
                    my.re.bottom= cancely +r2;
                    g.drawBitmap(imgcancel,null,my.re,p);
                }
            }else{
                g.drawBitmap(img,null,my.re,p);
                if(jineng!=0 && cd>0) {
                    p.setTextSize(40*my.bili);
                    p.setColor(Color.WHITE);
                    g.drawBitmap(imgcd,null,my.re,p);
                    float f=cd/100f;
                    f=(int)f;
                    f=f/10;
                    g.drawText(String.valueOf(f),x-p.getTextSize()*4/5,y+p.getTextSize()/3,p);
    
                }
                my.re.left-=drawpx;
                my.re.top-=drawpx;
                my.re.right+=drawpx;
                my.re.bottom+=drawpx;
                g.drawBitmap(imgborder,null,my.re,p);
            }
        }
    }

    新建一个类 OnTouchSkill.java 他也是一个监听view

    这样多点触控会好写很多,刚开始我是用一个view做监听的 写到我心态爆炸。。。

    package com.yaogan.liziguo.yaogan;
    
    import android.content.Context;
    import android.graphics.Color;
    import android.view.MotionEvent;
    import android.view.View;
    
    /**
     * Created by Liziguo on 2018/6/16.
     */
    
    public class OnTouchSkill extends View {
        /*
        A 普通攻击
        Q 技能1
        W 技能2
        E 技能3
        R 没有R
         */
    
        public Skill A,Q,W,E;
    
        public OnTouchSkill(Context context,Skill a,Skill q,Skill w,Skill e) {
            super(context);
            A=a;Q=q;W=w;E=e;
            setBackgroundColor(Color.WHITE);
            getBackground().setAlpha(my.ontouchAlpha);//0-255
            setOnTouchListener(new OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent ev) {
                    final float xx = ev.getX() + getX(), yy = ev.getY() + getY();
                    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
                        if ( A.in(xx, yy)) {
                            A.down();
                        } else if ( Q.in(xx, yy)) {
                            Q.down();
                        } else if ( W.in(xx, yy)) {
                            W.down();
                        } else if ( E.in(xx, yy)) {
                            E.down();
                        }
    
                    }
                    if (my.skill != null) my.skill.move(xx, yy);
                    if(ev.getAction()==MotionEvent.ACTION_UP){
                        A.down = false;
                        Q.down = false;
                        W.down = false;
                        E.down = false;
                    }
                    return true;
                }
            });
        }
    }

    把监听控件添加到Hua,修改 Hua.java

    package com.yaogan.liziguo.yaogan;
    
    import android.content.Context;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.widget.RelativeLayout;
    
    /**
     * Created by Liziguo on 2018/6/15.
     */
    
    public class Hua extends RelativeLayout implements Runnable{ //继承RelativeLayout 实现Runnable接口
    
        private Paint p;//画笔
        private Move m=new Move();//移动摇杆
    
         /*
        A 普通攻击
        Q 技能1
        W 技能2
        E 技能3
        R 没有R
         */
    
        public Skill A=new Skill(0,100, BitmapFactory.decodeResource(getResources(),R.mipmap.putonggongji)) {
            @Override
            public void down_main() { }
            @Override
            public void move_main() { }
            @Override
            public void up() { }
        };
        public Skill Q=new Skill(1,1000, BitmapFactory.decodeResource(getResources(),R.mipmap.skill1)) {
            @Override
            public void down_main() { }
            @Override
            public void move_main() { }
            @Override
            public void up() {
                down_main=false;
                if(!cancel){ //技能冷却时间
                    last= System.currentTimeMillis();
                }
            }
        };
        public Skill W=new Skill(2,1000, BitmapFactory.decodeResource(getResources(),R.mipmap.skill2)) {
            @Override
            public void down_main() { }
            @Override
            public void move_main() { }
            @Override
            public void up() {
                down_main=false;
                if(!cancel){
                    last= System.currentTimeMillis();
                }
            }
        };
        public Skill E=new Skill(3,1000, BitmapFactory.decodeResource(getResources(),R.mipmap.skill3)) {
            @Override
            public void down_main() { }
            @Override
            public void move_main() { }
            @Override
            public void up() {
                down_main=false;
                if(!cancel){
                    last= System.currentTimeMillis();
                }
            }
        };
    
        public Hua(Context context) {
            super(context);
            p=new Paint();
            setBackgroundColor(Color.BLACK);//背景颜色设为黑色
            //实例化一个OnTouchMove
            OnTouchMove onTouchMove=new OnTouchMove(context,m);
            //把onTouchMove添加进来 宽度为屏幕的1/3 高度为屏幕的1/2
            addView(onTouchMove,my.w/3,my.h/2);
            //设置onTouchMove的位置
            onTouchMove.setX(0);
            onTouchMove.setY(my.h/2);
    
            //添加技能摇杆监听
            OnTouchSkill onTouchSkill=new OnTouchSkill(context,A,Q,W,E);//后添加的优先级高
            addView(onTouchSkill);
            onTouchSkill.setX(my.w*0.7f-85*my.bili);
            onTouchSkill.setY(my.h/2-85*my.bili);
            new Thread(this).start();//启动重绘线程
        }
    
        @Override
        protected void onDraw(Canvas g) {//重写onDraw方法
            super.onDraw(g);
            m.onDraw(g,p);//画移动摇杆
            //画技能
            A.onDraw(g,p);
            Q.onDraw(g,p);
            W.onDraw(g,p);
            E.onDraw(g,p);
        }
    
        @Override
        public void run() { //每隔20毫秒刷新一次画布
            while(true){
                try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}
                //计算冷却时间
                A.next();
                Q.next();
                W.next();
                E.next();
                //释放技能
                if (my.skill != null) {
                    my.skill.down_main();//教程用不到该方法
                    my.skill.move_main();//教程用不到该方法
                    if (my.skill.down == false) {
                        my.skill.up();
                        my.skill = null;
                    }
                }
    
                postInvalidate();//重绘 在子线程重绘不能调用Invalidate()方法
            }
        }
    }

    运行下看看效果吧

    修改 my.java

    public class my { //这个类当一个全局变量使用
        public static int w,h;//屏幕的宽高
        public static float bili;
        public static MainActivity main;
        public static RectF re=new RectF();
        public static int ontouchAlpha=0;//把触控区透明度改成0
    
        public static Bitmap border,cancel,down,yaogan,cd;
    
        public static Skill skill;//当前正在使用的技能
    }

     

    再运行下

     

    大功告成

    下载地址:https://download.csdn.net/download/u010756046/10482434

    PS:图片不要太大 尽量压缩到20kb以下,不然使用摇杆会很卡

     

    展开全文
  • 现在许多手机看cad图纸的app,请问这些APP大概是怎么开发的呢。比如使用什么语言,什么api等等
  • Android 音视频开发学习思路大纲

    千次阅读 2020-08-25 17:41:52
    前言 大家都知道,2019年是5g元年,随着5g的崛起,音视频将会运用的更加...Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的。只能通过一点点的学习和积累把这块的知识串联

    前言

    大家都知道,2019年是5g元年,随着5g的崛起,音视频将会运用的更加的广阔(比如远程教学,在线教学,在线会议,远程互动,安防监控…),将不再单单局限与目前的泛娱乐平台,将会更加的完善,从而更好的服务于我们的生活。

    本人是非常爱好音视频开发的,奈何音视频的开发是有一定难度的,因为他涉及的层面比较广,要想深入学习,是需要有一定的学习体系,然后一步一个脚印的深入的。

    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的。只能通过一点点的学习和积累把这块的知识串联积累起来。接下来,我会把目前网络大牛学习音视频过程做一个条目整理,希望可以帮助所有想学习音视频开发的小伙伴,在以后,我也会严格按照这些条目列表一步一步实现。

    理论知识篇:

    基础知识是基础中的基础,它涉及到了很多理念性的知识,也是学习音视频入门的必备基础知识。常用的基础知识主要包括了以下几个概念:

    • 码率
    • 帧率
    • 分辨率
    • 清晰度
    • 声道
    • 位深度

    初级入门篇:

    • Android 音视频开发(一) : 通过三种方式绘制图片
    • Android 音视频开发(二):使用 AudioRecord 采集音频PCM并保存到文件
    • Android 音视频开发(三):使用 AudioTrack 播放PCM音频
    • Android 音视频开发(四):使用 Camera API 采集视频数据
    • Android 音视频开发(五):使用 MediaExtractor 和 MediaMuxer API 解析和封装 mp4 文件
    • Android 音视频开发(六): MediaCodec API 详解
    • Android 音视频开发(七): 音视频录制流程总结

    初级入门篇主要是接触Android多媒体展示相关的API,通过单独的列举和使用这些API,对Android音视频处理有一个基本的轮廓,虽然知识点相对来说是比较散的,但是点成线,线称面,基本的基础掌握了,通过学习Android音视频核心的API将音视频的流程串联起来,这样对于音视频的了解和控制就不仅仅局限于最外层的API了,而是能够通过相对底层的方式来加深对Android 音视频开发的认知。

    中级晋级篇:

    了解了系统基本的API,我们基本算是步入了音视频开发的大门,但是,到了这一步也仅仅是入门而已。需要我们进一步深入学习,做好晋级的准备。下面是晋级所必须要走过的每一步。

    • 在 Android 平台绘制一张图片,使用至少 3 种不同的 API,ImageView,SurfaceView,自定义 View
    • 了解并搭建OpenGL ES 环境
    • OpenGL ES 定义形状。
    • OpenGL ES 定义形状
    • OpenGL ES 绘制形状
    • OpenGL ES 使用投影和相机视图
    • OpenGL ES 添加运动效果
    • OpenGL ES 响应触摸事件
    • OpenGL ES 着色器语言GLSL
    • OpenGL ES 纹理贴图
    • 通过GLES20与着色器交互

    到了这个阶段,OpenGL ES的API我想应该有了一定的了解,下面就是要学以致用,根据这些API做一些简单的实战。

    • 使用 OpenGL 绘制一个三角形
    • 学习纹理绘制,能够使用 OpenGL 显示一张图片

    终极晋级篇:

    如果,你已经掌握了前面的3个阶段的相关技术,接下来,就要步入终极技术的实战,终极篇是学会了,那么你就是一个真正意义上的音视频大牛,这也是从事音视频技术开发的分水岭,更是拿高工资的杀手锏。它主要包括了一下东西:

    1.编码和解码:

    • 学习 MediaCodec API,完成音频 AAC 硬编、硬解
    • 学习 MediaCodec API,完成视频( H.264 , H.2645)的硬编、硬解

    2.音视频录制流程:

    • 串联整个音视频录制流程,完成音视频的采集、编码、封包成 mp4 输出
    • 串联整个音视频播放流程,完成 mp4 的解析、音视频的解码、播放和渲染

    3.深入学习OpenGL:

    • 进一步学习 OpenGL,了解如何实现视频的剪裁、旋转、水印、滤镜,并学习 OpenGL 高级特性,如:VBO,VAO,FBO…
    • 学习 Android 图形图像架构,能够使用 GLSurfaceviw 绘制 Camera 预览画面
    • 使用 OpenSL 播放 PCM 数据
    • Android OpenSL 录制 PCM 音频数据
    • OpenSL ES利用SoundTouch实现PCM音频的变速和变调

    4.深入图像处理算法的研究:

    大家都知道,视频其实就是一张一张的图片合成的,现在很多应用都是需要对视频做一些美颜特效,或者后期视频特效的处理,因此,必须要掌握先关的图像处理算法,图像处理基本算法操作从处理对象的多少可以有如下划分:

    1. 点运算:处理点单元信息的运算
    2. 群运算:处理群单元 (若干个相邻点的集合)的运算

    进一步分类如下列表所示:

    操作类型具体的操作
    点运算二值化操作、直方图处理、亮度映射、加法运算、翻转运 算 、尺度运算 、对数运算 、指数运算等
    群运算模板卷积运算、滤波运算(均值滤波、最大值滤波 、最小值滤波,以及常见的高斯滤波器)、各项异性扩散、形态学操作(膨胀和腐蚀)、力场变换等

    5.相关网络协议:

    • 深入研究音视频相关的网络协议,如 rtmp,hls,以及封包格式,如:flv,mp4
    • 深入学习一些音视频领域的开源项目,如 webrtc,ffmpeg,ijkplayer,librtmp 等等

    6.多媒体文件格式:

    • 多媒体文件格式之MP4 格式
    • 多媒体文件格式之FLV 格式
    • 多媒体文件格式之M3U8 格式
    • 多媒体文件格式之TS 格式
    • 多媒体文件格式之PCM / WAV 格式

    7.相关开源库文件的移植:

    • 将 ffmpeg 库移植到 Android 平台,结合上面积累的经验,编写一款简易的音视频播放器
    • 将 x264 库移植到 Android 平台,结合上面积累的经验,完成视频数据 H264 软编功能
    • 将 librtmp 库移植到 Android 平台,结合上面积累的经验,完成 Android RTMP 推流功能

    关于ffmpeg 库文件的学习是比较枯燥,也是至关重要的,因此一定要耐着性子认认真真,抽丝剥茧的去学,不懂的可以百度查阅资料,看相关的技术的博客,下面推荐几个比较好的博主,后期,我也会进一步深入研究ffmpeg,这里,就不误导大家了。

    1. 博客园的灰色飘零大佬
    2. 51CTO的Jhuster的专栏的FFMPEG Tips专栏
    3. CSDNywl5320专栏
    4. CSDN雷神FFMPEG专栏

    8.常用的视频播放开源库:

    9.终极实战:

    • 如果你掌握了上述所有的功能,那么,你可以尝试做一款短视频 APP,完成如:断点拍摄、添加水印、本地转码、视频剪辑、视频拼接、MV 特效,视频美颜,实时推流(类似抖音)互动等功能。

    总结:

    “路漫漫其修远兮,吾将上下而求索”。如果,你掌握了这些技能,我相信你将是音视频开发领域的大亨,香饽饽。从此走上人生巅峰,成功迎娶白富美。在以后的日子里,我也会围绕这个大纲,站在以前巨人的肩膀上,一步步深入音视频,一步步完善这些博客。

    推荐
    下面是我在做音视频开发以及图像处理算法时经常参考的资料以及膜拜的大神。

    1. 图像处理算法大佬:https://www.cnblogs.com/Imageshop/,代表作ImageShop,一款小巧强大的ps处理软件
    2. CSDN雷神《雷霄骅的专栏》
    3. 51CTO《Jhuster的专栏》
    4. 《Learn OpenGL 中文》
    5. 《Android Graphic 架构》
    6. CSDN《ywl5320的专栏》
    展开全文
  • 最近有网友留言说让介绍一下xCombine开发的大概思路,之前因为比较忙,一直没有写过介绍,现在简单介绍一下吧。 为什么要使用插件式框架,android的插件限制这么多为什么还要使用这种机制?我想大家都会有这样的...
  • Android二维码扫描开发:实现思路与原理.pdf
  • android 短视频 开发 思路 简单记录

    千次阅读 2016-01-20 11:23:55
    1.通过mediaRecorder录制视频 2.通过isoviewer将分段的mp4合并 3.通过ffmpeg提取出mp4中的音频 4.通过sox合并提取出的音频和要添加的背景音乐 5.通过ffmpeg的命令行调用,实现...7.通过ffmpeg的
  • android开发

    千次阅读 2014-06-25 16:46:38
    android开发学习 一、 基础  1、熟练掌握基本控件以及容器控件的使用 ;  常用的基本控件有:Button 、TextView、EditText、ListView等  常用的容器控件有:FrameLayout、LinearLayout、RelativeLayout等  2、...
  • android 开发讲义

    2010-09-14 17:32:27
    用于对ANDROID 初学者使用,并建立有序的开发思路,为更深层次开发打下基础。
  • 主要介绍了Android应用开发中实现apk皮肤文件换肤的思路分析,包括布局和主要的皮肤更换逻辑实现,需要的朋友可以参考下
  • android音乐播放器开发 SweetMusicPlayer 实现思路

    千次阅读 多人点赞 2014-10-07 17:56:41
    android音乐播放器开发 SweetMusicPlayer 加载歌词列表 一,加载
  • Android开发手机通讯录

    千次阅读 多人点赞 2019-12-19 01:28:06
    Android Studio开发手机通讯录课程设计课程设计要求课程设计题目题目1 通讯录管理题目2 拨号和短信...经过一个学期的Android开发学习,本次学期末,为了检验大家的学习情况,此次期末的课程设计为使用Android Studio...
  • Android逆向工具基础思维导图,便捷整理思路,环境配置、Android开发环境、安卓模拟器、一台调试手机、调试方法
  • Android开发过程之实例讲解前言 回过头来审视之前做过的Android项目,发觉自己重新开发时忽然间不知所措了,间隔了太长时间没有开发导致自己的Android技能知识急剧下降。温故而知新。 废话少说,进入正题~ 下面主要...
  • android开发智能家居

    2015-07-12 13:32:31
    想要做android开发智能家居的朋友们看看了,可以拓宽思路啊!
  • 基于Android开发的天气预报app(源码下载)

    万次阅读 多人点赞 2017-05-25 20:37:35
    基于AndroidStudio环境开发的天气app -系统总体介绍:本天气app使用AndroidStudio这个IDE工具在Windows10系统下进行开发。主要实现了:1、定位城市天气显示;2、城市编辑功能(增、删、改、查)以及对应天气显示...
  • 最近在做一款相机相关app,因为里面功能蛮多,所以除了基本的相机操作,其他的像慢动作、延时摄影、滤镜、直播这些都很费工夫,那么今天就来和大家探讨一下延时摄影的一些实现思路。  延时摄影,简单来讲就是将一段...
  • @Override public int compareTo(JTTreeInfo another) { //进行排序,用Collections.sort 可以升序排列 CameraPosition camera = JTGeoEngine.getInstance().getCameraPosition(); GLKVector3 otherPosition = ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 73,082
精华内容 29,232
关键字:

android开发思路