《第一行代码 Android》

AndroidManifest

活动注册, 所有活动都需要在该文件中进行注册之后才能生效。

活动的生命周期

  • onCreate()
    活动第一次被创建的时候调用,这个方法中完成活动如加载布局、绑定事件的初始化操作。
  • onStart()
    活动变得可见时被调用
  • onResume()
    活动准备好和用户进行交互的时候调用。
  • onPause()
    系统准备去启动或者回复另一个活动的时候调用
  • onStop()
  • onDestroy()
  • onRestart()

特殊类

Calendar

View

Paint

Canvas

数据

持久化操作

组件收录

View类是用户组件的共同父类,几乎所有用户界面组件都是继承View类实现。
'android:backgroup':设置背景颜色;
'setBackgroudColor()':对应方法;
'android:id':为组件设置可通过findViewById方法获取的标识符;
'setId()':对应方法;
'findViewById()':对应方法;
'android:alpha':设置透明度,取值为0~1;
'setAlpha()':对应方法;
'android:visibility':
控制组件的可见熟悉,可选visible(可见)、invisible(不可见,仍然占据原来的位置与空间)、gone(表示组件不仅不可见,而且不再占用任何屏幕空间);
'setVisibility()':
通过代码通过传入View.VISIBLE/INVISIBLE/GONE控制控件的可见性;
’getVisibility()':
获取当前可见性;
'android:clickable':设置组件是否响应单击事件;

TextView

'android:text':指定TextView中显示的文本内容;
’android:gravity‘:来指定文字的对齐方式,可选top、bottom、left、right、center等,通过’|‘来同时指定多个值表‘且’;
'android:textSIze':文字大小;
'android:textColor’:文字颜色;

Button

该组件可控制的属性与TextView差不多。系统会对Button中的文字自动进行大写转换。
'android:textAllCaps':选择‘false’禁止大写转换;
‘setOnClickListener’:传入一个实现了onClick()方法的对象;

EditText

允许在组件中输入和编辑内容,并可以在程序中对这些内容进行处理。
'android:editable':为ture时,设置可编辑;
'android:numeric':只能输入数字,interger(输入数值)/signed(输入带符号的数值)/decimal(输入带小数点的数值)
'android:password':为true时,密码输入字符显示为原点;
'android:phoneNumber':为true时,只能输入电话号码;
‘android:hint':指定提示性文本;
'android:maxLines':规定编辑框可显示内容的最大行数,超出后会滚动;
’getText()‘:获取EditText组件中输入的内容,不过需要通过调用toString()转换成字符串;

ImageView

该组件需要的图片一般放在‘drawable'目录中,不过该目录未指定具体的分辨率,可以新建后缀为’-xhdpi‘的文件将图片放于其中。

可操作的空间

‘android:src’:为当前ImageView直接指定一张图片;
’setImageResource()‘:代码动态更改ImageView中图片的方法;

ProgressBar

‘android:max’:给进度条设置一个最大值;
'get/setProgress()':获取/设置当前进度条进度;

SeekBar

拖动条,允许用户拖动滑块改变值。该组件可以通过‘android:thumb’属性实现,该属性的值为一个Drawable对象,该对象将作为自定义滑块。

seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
  @Override
  public void onStopTrackingTouch(SeekBar seekBar){
    //结束滑动时候应运行逻辑    
  }
  @Override
  public void onStartTrackingTouch(SeekBar seekBar){
    //开始滑动时候应运行逻辑
  }
  @Override
  public void onProgressChanged(SeekBar seekBar,int progress,boolean fromUser){
    //当前进度条的值应运行的逻辑
  }

ListView

listview用于展示大量数据,允许通过手指上下滑动的方式将屏幕外的数据滚到屏幕内。
一般数组中的数据无法直接传递给ListView,需要借助适配器完成,Android里面有大量的适配器的实现类,适配器的任务便是生成ListView中的一个个View子项目。所以适配器在这一刻的主要工作便是将回调函数getView()具体实现,在该回调方法中将对象中存储的数据一项一项的传递给子项目布局的各个组件当中。各个适配器中较为常用的为ArrayAdapter,可以用泛型来指定要适配的数据类型,然后在构造函数当中将数据传入。
其次与ListView相关的运用还有ListView的子项目的点击事件。(果然,,记太多都会忘,还是看官方备注实在)

    /* 该接口的实现在ListView中的子项目被点击时候回调*/
    public interface OnItemClickListener {
        /**
         * 如果需要访问与所该子项目关联的数据,可以通过调用getItemAtPosition(position)获取
         * @param parent:该点击事件对应的AdapterView适配器对象。
         * @param view:被单击的AdapterView中的子视图(由适配器提供的视图) 
         * @param position:子视图在适配器中的位置。
         * @param id:被单击项目的行id。
         */
        void onItemClick(AdapterView<?> parent, View view, int position, long id);
    }
ArrayAdapter适配器

以ArrayAdapter适配器举例,ArrayAdapter的构造函数中需要依次传入当前上下文、ListView子项布局的id、以及所适配的数据,最后调用ListView的setAdapter()方法,将构建好的适配器对象传递进去,将ListView与数据联系起来。
适配器需要定义一用于传递数据的适配类。
适配器的构造函数用于将上下文,子项布局的id和数据传递进来。
适配器需要重写getView(),该方法在每个子项被滚到屏幕内时被调用,在方法中首先需要得到当前项的实例,然后使用LayoutInflater来为这个子项加载需要传入的布局。

public class AdapterClass{
//* 定义域、构造函数、基本getter、setter方法*//
}
public class MyAdapter extends ArrayAdapter<AdapterClass>{
//*定义额外需要的域*//
  public MyAdapter(Context context,int textViewResourceId,List<AdapterClass> objects){//textViewResourceId为子项布局id
    super(context,textViewResourceId,objects);
    //*初始化自己的域*//
  }
  @Override
  public View getView(int positon,View convertView,ViewGroup parent){//该方法为ArrayAdapter的方法,其中position参数为实例在数组中的位置,convertView为上下文布局()
    AdapterClass theObject = getItem(position);
    View view  = LayoutInflater.from(getContext()).inflate(子项布局id,parent,false);//参数false表示只让我们在父布局中声明的layout属性生效,但不会为这个View添加父布局,因为一旦有了父布局,就不能再添加到ListView组件当中。
    //*获取组件,并用适当方法向组件中添加适配类中的数据*//
    return view;
  }
}
public class MainActivity extends AppCompatActivity{
  //*域*//
  @Override
  protected void onCreate(Bundle savedInstanceState){
    //*其它操作*//
    MyAdapter myAdapter  = new MyAdapter(MainActivity.this,R.layout.*,adpterClassList);//此处第三个参数为其它地方已经实例化了的ArrayList对象
    //当需要传入的布局足够简单的时候可以调用库中的已有布局,比如'android.R.layout.simple_list_item_1'便是一个简单的TextView布局,适用于单纯的字符串。
    ListView listView = (ListView) findViewById(R.id.*);
    listView.setAdapter(myAdapter);
  }
}
  
//
  private class MyAdapter extends BaseAdapter {
        // 其它方法或域
        @Override
        public View getView(int position, View convertView, ViewGroup container) {
            if (convertView == null) {
                convertView = getLayoutInflater().inflate(R.layout.list_item, container, false);
            }
  
            ((TextView) convertView.findViewById(android.R.id.text1))
                    .setText(getItem(position));
            reoturn convertView;
        }
    }

TimePicker

DatePicker

概念收录

运行时权限

运行时权限功能在6.0之后启用,首先运用的权限调用声明在AndroidManifest.xml文件中。

所有权限中只有危险权限和特殊权限需要在运行时申请,其它普通权限由系统自动授权。危险权限常常为会触及用户隐私或者对设备安全造成影响的。

危险权限一共有九组,24个权限。危险权限的授权按组进行,同一组的权限申请成功一个,则同组其它也获权成功。

权限声明语法:

//Android Manifest.xml中
<uses-permission android:name="android.permission.*"/>
/*危险权限除了声明之外,6.0以上的系统还需要在代码中添
加运行时权限处理,处理的内容主要为:由用户授权我们去
执行某些危险操作。*/
//运行时权限声明
/*判断用户是不是已经给过授权的方法*/
ContextCompat.checkSelfPermission(*Activity.this,Manifest.permission.*)==PackageManager.PERMISSION_GRANTED
/*申请授权*/
//传入一个需要申请权限的数值,以及请求码,供回调函数(下面重写的那个)处理。处理结果封装在grantResults中
ActivityCompat.requestPermissions(*Activity.this,new String[] {Manifers.permission.*,...},requestCode)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults){
  switch(requestCode){
    if(grantResults.length>0&&grantResults[0]==PackageManager.*)
      //*
      else
      //*
    }
  }
}

应用收录

选项菜单

首先在资源目录中新建menu包,在其中新建一个main.xml文件,用于绘制菜单

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/main_item"
        android:title="@string/menu_title4"
        />
    <!--依次添加菜单项-->
</menu>

接着在需要展示选项菜单的活动中重写两个重要方法

public boolean onCreateOptionsMenu(Menu menu){
  //首先获取MenuInflater对象,然后通过inflate给当前活动创建菜单,语法大意为根据R.main.menu处的资源文件制定菜单,并将菜单项添加到menu对象中
  getMenuInflater().inflate(R.menu.*,menu);
  return turn;
}

public boolean onOptionsItemSelected(MenuItem item){
  switch(item.getItemId()){
    /*编写各个选项被选中后应该执行的操作*/
  }
}

上下文菜单

上下文菜单类似于计算机上的右键菜单,该菜单与选项菜单不同的地方在于该菜单是长按某一项目时候调出,出现于上下文。

//*绘制上下文菜单,添加菜单项与菜单标题等*//
public void onCreateContextMenu(ContextMenu menu,View v,ContextMenu.ContextMenuInfo menuInfo){
  
}
//*处理菜单点击事件*//
public boolean onContextItemSelected(MenuItem item){

}
//*在onCreate方法中调用registerForContextMenu方法,为视图注册上下文菜单
registerForContextMenu(<? extends View>);

对话框

  • 首先如果有需要,可以绘制对话框的布局,按照正常文件的编写方法进行编写即可。若只是提示框可以不需要进行布局文件的编写
  • 其次将对话框对象实例化,通过调用方法对对话框进行设置
AlertDialog.Builder dialog = new AlertDialog.Builder(<? extends context>)
/*设置各个属性*/
/*
setTitile();
setMessage();
setPositiveButton();:设置类似于确定的积极按键,并传入点击事件的对象
setNegativeButton();:设置类似于取消的消极按键,并传入点击事件的对象
setView();
*/
/*创建并在合适的时候展示对话框*/
dialog.create();
dialog.show();
/*取消、完成对话框*/

Android的MVC设计模式

将布局文件作为表现层(View),将Activity的子类作为控制层(Control),并新建继承了View的新类作为业务模型层。编写的业务模型层中含有其应具备的属性、行为,并且可以用于布局当中。

绘图

  • 创建一个View的子类,重写onDraw()系统回调方法。
    在onDraw()方法当中,运用画布Canvas对象与绘笔Paint对象绘制所需要的控件,甚至可以为其赋予属性。
  • 通过invalidate()方法可以在控制层中刷新该自定义控件的状态。

自定义组件

该运用与绘图中的MVC设计模式类似,

//自定义组件的类
public class MyLayout extends LinearLayout{
  public MyLayout(Context context,AttributeSet attrs){
    super(context,attrs);
    //在构造函数中需要对标题栏布局进行动态加载,如下语句中from()方法可以构建出一个LinearLyoutInflater对象,然后调用inflate方法可以动态加载一个布局文件,其中第一个参数是要加载的布局文件的id,第二参数为给加载好的布局添加一个父布局
    LayoutInflater.from(context).infalte(R.layout.title.,this);
    }
}
//

触摸事件

触摸事件的核心是OnTouchListener监听接口中监听方法onTouch(View v,MotionEvent event)的实现。

音频文件播放

android提供MediaPlayer类播放音频,


image.png

视频文件播放

照相机

取景:利用Surface组件进行取景,然后通过SurfaceHolder.Callback监控取景视图,Callback接口有下面三个方法需要实现。

   @Override
    public void surfaceCreated(SurfaceHolder holder) {
       //用于初始化
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
        //当景物发生变化时候触动
    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
        //释放对象时候触动
    }

在需要实现的地方实现如下逻辑

        /*SurfaceView监听图像——常在onCreate()函数中*/
        surfaceView = findViewById(R.id.*);
        SurfaceHolder holder = surfaceView.getHolder();
        //注册回调监听器
        holder.addCallback(this);
        //设置SurfaceHolder的类型        
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        /*初始化相机——常在surfaceCreated()函数中*/
        //打开系统相机
        Camera camera = Camera.open();
        //为相机指定一个用来显示相机预览画面的SurfaceView
        camera.setPreviewDisplay(holder);
        /*设置相机取景参数——常在surfaceChanged()函数中*/
        Camera.Parameters parameters = camera.getParameters();
        //相片格式
        parameters.setPictureFormat(PixelFormat.JPEG);
        //预览画面的大小
        parameters.setPreviewSize(320,240);
        //设置图片分辨率大小
        parameters.setPictureSize(320,240);
        //将参数作用于对象
        camera.setParameters(parameters);
        //开始预览
        camera.startPreview();
        /*拍照*/
/*public final void takePicture(ShutterCallback shutter,PictureCallback raw,PictureCallback postview,PictureCallback jpeg):
 /*触发异步图像捕获。相机服务将在图像捕获过程中启动一
系列对应用程序的回调。快门回调发生在图像被捕获之后。
这可以用来触发一个声音,让用户知道图像已经捕获。原始
图像回调发生在原始图像数据可用的时候(注意:如果没有可
用的原始图像回调缓冲区或原始图像回调缓冲区不够大容纳
原始图像,数据将为空)。postview回调发生在缩放后的,
完全处理后的图像是可用的(注意:并非所有硬件都支持此功
能)。jpeg回调在压缩图像可用时发生。如果应用程序不需
要特定的回调,则可以传递null而不是回调方法。
*/
        //照相,同时传入上诉说明中自身所需要的回调函数
        camera.takePicture(null,null,new jpegCallback());
        /*定义回调函数进行压缩照片或其它操作——常作为参数传入takePicture()函数进行回调*/
        //用压缩相片举例,重写Camera.PictureCallback接口中的方法
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            //建立图像对象
            Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length);
            try{
                //建立输出流对象
                BufferedOutputStream outStream = new BufferedOutputStream(new FileOutputStream(path));
                //采用压缩转档方法
                bitmap.compress(Bitmap.CompressFormat.JPEG,80,outStream);
                //更新缓冲流
                outStream.flush();
                outStream.close();
                //显示拍照的图片(此处省去imageView的声明、赋值操作)
                imageView.setImageBitmap(bitmap);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
       

异常收录

疑问收录

  • 子项布局id具体为何物:
    子项布局id为作为某一组件的子项的布局id(说了个寂寞),具体表现为R.layout.,其中xml处的文件。
  • 安卓的文件怎么访问,根目录在哪
    参考博客
/*返回文件系统上存储用openFileOutput创建的文件的目录
的绝对路径。如果调用应用程序被移动到所采用的存储设
备,返回的路径可能会随着时间而改变,因此只应该持久化
相对路径。*/
getFilesDir();
/*返回主共享/外部存储设备上的目录的绝对路径,应用程序
可以在其中放置它所拥有的持久文件。这些文件是应用程序
内部的,通常不作为媒体对用户可见。*/
getExternalFilesDir("exter_test").getAbsolutePath();
//返回下载/缓存内容目录。
Environment.getDownloadCacheDirectory().getAbsolutePath();
//返回用户数据目录。
Environment.getDataDirectory().getAbsolutePath()
/*返回主共享/外部存储目录。如果该目录已被用户挂载到其
计算机上,或已从设备中删除,或发生了其他问题,则当前
可能无法访问该目录。可以使用getExternalStorageState()
来确定它的当前状态。(不要被“外部”这个词搞糊涂了。这
个目录可以被更好地理解为媒体/共享存储。它是一个文件
系统,可以保存相对大量的数据,并在所有应用程序之间共
享(不强制执行权限)。传统上这是SD卡,但它也可以实现为
设备中的内置存储,与受保护的内部存储不同,并可以作为
计算机上的文件系统安装。)*/
Environment.getExternalStorageDirectory().getAbsolutePath();
/*获取用于放置特定类型文件的顶级共享/外部存储目录。这
是用户通常放置和管理自己的文件的地方,所以您应该小心
您在这里放置的文件,以确保您不会擦除他们的文件或妨碍
他们自己的组织。(这个目录可能还不存在,所以在使用它
之前必须确保它存在,比如使用File.mkdirs()。)*/
7Environment.getExternalStoragePublicDirectory("pub_test")

执行结果依次为:
getFilesDir = /data/user/0/com.example.lab_5/files
getExternalFilesDir = /storage/emulated/0/Android/data/com.example.lab_5/files/exter_test
getDownloadCacheDirectory = /cache
getDataDirectory = /data
getExternalStorageDirectory = /storage/emulated/0
getExternalStoragePublicDirectory = /storage/emulated/0/pub_test
2021-11-16 16:53:12.342 14592-146
  • Android平台的app为什么不能随意创建文件夹(本想创建在最容易找到地方,却被告之没有权限)
    参考文献
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容