赞
踩
java:我们写Java代码的地方,业务功能都在这里实现
res:存放我们各种资源文件的地方,有图片,字符串,动画,音频等,还有各种形式的XML文件
所有的资源文件都会在R.java文件下生成对应的资源id,我们可以直接通过资源id访问到对应的资源。使用mipmap会在图片缩放在提供一定的性能优化,分辨率不同系统会根据屏幕分辨率来选择hdpi,mdpi,xmdpi,xxhdpi下的对应图片,所以你解压别人的apk可以看到上述目录同一名称的图片,在四个文件夹下都有,只是大小和像素不一样而已!当然,这也不是绝对的,比如我们把所有的图片都丢在了drawable-hdpi下的话,即使手机 本该加载ldpi文件夹下的图片资源,但是ldpi下没有,那么加载的还会是hdpi下的图片! 另外,还有一种情况:比如是hdpi,mdpi目录下有,ldpi下没有,那么会加载mdpi中的资源! 原则是使用最接近的密度级别!另外如果你想禁止Android不跟随屏幕密度加载不同文件夹的资源,只需在AndroidManifest.xml文件中添加android:anyDensity="false"字段即可!
1.图片资源
drawable :存放各种位图文件,(.png, .jpg, .9png, .gif等)除此之外可能是一些其他的drawable类型的xml文件
mipmap-hdpi:高分辨率,一般把文件放这里
mipmap-mdpi:中分辨率,很少,除非兼容的手机很久
mipmap-xhhdpi:超高分辨率,手机屏幕材质越来越好,以后会慢慢向这里过度。
mipmap-xxhdpi:超超高分辨率,高端机可以用
mipmap-xxhdpi:超超超高分辨率,牛
2.布局资源
layout :该目录下存放的就是我们的布局文件,另外在一些特定的机型上,要做屏幕适配,比如480320这样的手机,我们会另外创建一套布局,比如layout-480320这样的文件夹
3.菜单资源(无)
menu:在以前有物理菜单按钮,即有menu键的手机上用的较多,菜单项相关的资源xml可在这里编写
4.values目录
colors.xml:定义颜色资源
string.xml:定义字符串资源
styles.xml:定义样式资源
5.raw目录(无)
用于存放各种原生资源(音频,视频,一些XML文件等),我们可以通过openRawResource(int id)来获得资源的二进制流!其实和Assets差不多,不过这里面的资源会在R文件那里生成一个资源id而已
6.最后还有个动画的,动画有两种(无)
属性动画和补间动画:
animator:存放属性动画的XML文件
anim:存放补间动画的XML文件
我们所有的资源文件都会在R.java文件下生成一个资源id,我们可以通过这个资源id来完成资源的访问,使用情况有两种:Java代码中使用和XML代码中使用。
Java代码中使用:
文字:txtName.setText(getResources().getText(R.string.name));
图片:imgIcon.setBackgroundDrawableResources(R.drawable.icon);
颜色:txtName.setTextColor(getResources().getColor(R.color.red));
布局:setContentView(R.layout.main);
控件:txtName=(TextView)findViewById(R.id.txt_name);
XML代码中使用:
通过@xxx即可得到,比如这里获取文本和图片:
MainActivity.java:
代码如下
package jay.com.example.firstapp;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
代码分析:
布局文件:activity_main.xml:
代码如下:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
代码分析:
AndroidManifest.xml配置文件:
代码如下:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
我要被android studio的ui布局气死了
文字表述:
事件监听机制中由事件源,事件,事件监听器三类对象组成 处理流程如下: Step 1:为某个事件源(组件)设置一个监听器,用于监听用户操作 Step 2:用户的操作,触发了事件源的监听器 Step 3:生成了对应的事件对象 Step 4:将这个事件源对象作为参数传给事件监听器 step 5:事件监听器对事件对象进行判断,执行对应的事件处理器(对应事件的处理方法)
归纳:
事件监听机制是一种委派式的事件处理机制,事件源(组件)事件处理委托给事件监听器 当事件源发生指定事件时,就通知指定事件监听器,执行相应的操作
我们以下面这个: 简单的按钮点击,提示Toast信息的程序;使用五种不同的形式来实现!
效果图:
平时最常用的一种:直接setXxxListener后,重写里面的方法即可; 通常是临时使用一次,复用性不高!
public class MainActivity extends Activity { private Button btnshow; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnshow = (Button) findViewById(R.id.btnshow); btnshow.setOnClickListener(new OnClickListener() { //重写点击事件的处理方法onClick() @Override public void onClick(View v) { //显示Toast信息 Toast.makeText(getApplicationContext(), "你点击了按钮", Toast.LENGTH_SHORT).show(); } }); } }
public class MainActivity extends Activity { private Button btnshow; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //二、使用内部类 button2=findViewById(R.id.button2); //直接new一个内部类作为对象 button2.setOnClickListener(new BtnClickListener()); } //定义一个内部类,实现View.OnClickListener接口,并重写onClick()方法 class BtnClickListener implements View.OnClickListener{ @Override public void onClick(View v){ Toast.makeText(getApplicationContext(),"按钮被点击了",Toast.LENGTH_SHORT).show(); } } }
就是另外创建一个处理事件的Java文件,这种形式用的比较少!因为外部类不能直接访问用户界面 类中的组件,要通过构造方法将组件传入使用;这样导致的结果就是代码不够简洁!
实现代码如下:
MyClick.java:
package com.jay.example.innerlisten; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; public class MyClick implements OnClickListener { private TextView textshow; //把文本框作为参数传入 public MyClick(TextView txt) { textshow = txt; } @Override public void onClick(View v) { //点击后设置文本框显示的文字 textshow.setText("点击了按钮!"); }
MainActivity.java
public class MainActivity extends AppCompatActivity {
TextView textView3;
Button button3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//三、使用外部类
button3=findViewById(R.id.button3);
textView3=findViewById(R.id.tex3);
button3.setOnClickListener(new MyClick(textView3));
}
}
只需要让Activity类实现XxxListener事件监听接口,在Activity中定义重写对应的事件处理器方法 eg:Actitity实现了OnClickListener接口,重写了onClick(view)方法在为某些组建添加该事件监听对象 时,直接setXxx.Listener(this)即可
实现代码如下:
MainAcivity.java
package com.jay.example.innerlisten; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import android.app.Activity; //让Activity方法实现OnClickListener接口 public class MainActivity extends Activity implements OnClickListener{ private Button btnshow; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnshow = (Button) findViewById(R.id.btnshow); //直接写个this btnshow.setOnClickListener(this); } //重写接口中的抽象方法 @Override public void onClick(View v) { Toast.makeText(getApplicationContext(), "使用Activity点击了按钮", Toast.LENGTH_SHORT).show(); } }
就是直接在xml布局文件中对应得Activity中定义一个事件处理方法 eg:public void myClick(View source) source对应事件源(组件) 接着布局文件中对应要触发事件的组建,设置一个属性:onclick = "myclick"即可
实现代码如下:
MainAcivity.java
package com.jay.example.caller; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.Toast; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } //自定义一个方法,传入一个view组件作为参数 public void myclick(View source) { Toast.makeText(getApplicationContext(), "标签按钮被点击了", Toast.LENGTH_SHORT).show(); } }
main.xml布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮"
android:onClick="myclick"/>
</LinearLayout>
文字表述:
答:是将功能定义与功能分开的一种手段,一种解耦合的设计思想;在Java中回调是通过接口来实现的,
作为一种系统架构,必须要有自己的运行环境,且需要为用户提供实现接口;实现依赖于客户,这样就可以
达到接口统一,实现不同,系统通过在不同的状态下"回调"我们的实现类,从而达到接口和实现的分离!
举个简单例子:
比如:你周五放学回家,你问你老妈煮好饭没,你妈说还没煮;然后你跟她说: 老妈,我看下喜羊羊,你煮好饭叫我哈!
分析:你和老妈约定了一个接口,你通过这个接口叫老妈煮饭,当饭煮好了的时候,你老妈 又通过这个接口来反馈你,“饭煮好了”!
在Android中基于回调的事件处理机制使用场景有两个:
常见View组件的回调
android为GUI组件提供了一些事件处理的回调方法,以View为例,有以下几个方法
代码示例
MyButton.java
public class MyButton extends Button{ private static String TAG = "呵呵"; public MyButton(Context context, AttributeSet attrs) { super(context, attrs); } //重写键盘按下触发的事件 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { super.onKeyDown(keyCode,event); Log.i(TAG, "onKeyDown方法被调用"); return true; } //重写弹起键盘触发的事件 @Override public boolean onKeyUp(int keyCode, KeyEvent event) { super.onKeyUp(keyCode,event); Log.i(TAG,"onKeyUp方法被调用"); return true; } //组件被触摸了 @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); Log.i(TAG,"onTouchEvent方法被调用"); return true; } }
布局文件:
<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"
tools:context=".MyActivity">
<example.jay.com.mybutton.MyButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮"/>
代码解析:
因为我们直接重写了Button的三个回调方法,当发生点击事件后就不需要我们在Java文件中进行
事件监听器的绑定就可以完成回调,即组件会处理对应的事件,即事件由事件源(组件)自身处理!
传播的顺序是: 监听器—>view组件的回调方法—>Activity的回调方法
事件传播的顺序 监听器优先,然后到View组件自身,最后再到Activity;返回值false继续传播,true终止传播~!
1.首先看一下学习路线图:
2.然后是Handler类的引入:
3.下面看一下Handler的执行流程图:
UI线程:就是我们的主线程,系统在创建UI线程的时候会初始化一个Looper对象,同时也会创建一个与其关联的MessageQueue;
Handler:作用就是发送与处理信息,如果希望Handler正常工作,在当前线程中要有一个Looper对象
Message:Handler接收与处理的消息对象
MessageQueue:消息队列,先进先出管理Message,在初始化Looper对象时会创建一个与之关联的MessageQueue;
Looper:每个线程只能够有一个Looper,管理MessageQueue,不断地从中取出Message分发给对应的Handler处理!
4.Handler的相关方法:
void handleMessage(Message msg):处理消息的方法,通常是用于被重写! sendEmptyMessage(int
what):发送空消息 sendEmptyMessageDelayed(int what,long
delayMillis):指定延时多少毫秒后发送空信息 sendMessage(Message msg):立即发送信息
sendMessageDelayed(Message msg):指定延时多少毫秒后发送信息 final boolean
hasMessage(int what):检查消息队列中是否包含what属性为指定值的消息 如果是参数为(int what,Object
object):除了判断what属性,还需要判断Object属性是否为指定对象的消息
5.Handler的使用示例:
1)Handler写在主线程中
在主线程中,因为系统已经初始化了一个Looper对象,所以我们直接创建Handler对象,就可以进行信息的发送与处理了!
2)Handler写在子线程中
如果是Handler写在了子线程中的话,我们就需要自己创建一个Looper对象了!创建的流程如下:
1 )直接调用Looper.prepare()方法即可为当前线程创建Looper对象,而它的构造器会创建配套的MessageQueue; 2
)创建Handler对象,重写handleMessage( )方法就可以处理来自于其他线程的信息了! 3
)调用Looper.loop()方法启动Looper
OnTouchListener相关方法与属性:
onTouch(View v, MotionEvent event):这里面的参数依次是触发触摸事件的组件,触碰事件event
封装了触发事件的详细信息,同样包括事件的类型、触发时间等信息。比如event.getX(),event.getY()
我们也可以对触摸的动作类型进行判断,使用event.getAction( )再进行判断;如: event.getAction ==
MotionEvent.ACTION_DOWN:按下事件 event.getAction ==
MotionEvent.ACTION_MOVE:移动事件 event.getAction ==
MotionEvent.ACTION_UP:弹起事件
同样是触碰事件,但是onTouchEvent更多的是用于自定义的view,所有的view类中都重写了该方法,而这种触摸事件是基于回调的,也就是说:如果我们返回的值是false的话,那么事件会继续向外传播,由外面的容器或者Activity进行处理!当然还涉及到了手势(Gesture),这个我们会在后面进行详细的讲解!onTouchEvent其实和onTouchListener是类似的,只是处理机制不用,前者是回调,后者是监听模式!
原理类的东西:
所谓的多点触碰就是多个手指在屏幕上进行操作,用的最多的估计是放大缩功能吧,比如很多的图片浏览器都支持缩放!理论上Android系统本身可以处理多达256个手指的触摸,当然这取决于手机硬件的支持;不过支持多点触摸的手机一般支持2-4个点,当然有些更多!我们发现前面两点都有用到MotionEvent,MotionEvent代表的是一个触摸事件;前我们可以根据event.getAction() & MotionEvent.ACTION_MASK来判断是哪种操作,除了上面介绍的三种单点操作外,还有两个多点专用的操作:
MotionEvent.ACTION_POINTER_DOWN:当屏幕上已经有一个点被按住,此时再按下其他点时触发。
MotionEvent.ACTION_POINTER_UP:当屏幕上有多个点被按住,松开其中一个点时触发(即非最后一个点被放开时)。
简单的流程大概是这样:
当我们一个手指触摸屏幕 ——> 触发ACTION_DOWN事件 接着有另一个手指也触摸屏幕 ——>
触发ACTION_POINTER_DOWN事件,如果还有其他手指触摸,继续触发 有一个手指离开屏幕 ——>
触发ACTION_POINTER_UP事件,继续有手指离开,继续触发 当最后一个手指离开屏幕 ——> 触发ACTION_UP事件
而且在整个过程中,ACTION_MOVE事件会一直不停地被触发
我们可以通过event.getX(int)或者event.getY(int)来获得不同触摸点的位置: 比如event.getX(0)可以获得第一个接触点的X坐标,event.getX(1)获得第二个接触点的X坐标这样… 另外,我们还可以在调用MotionEvent对象的getPointerCount()方法判断当前有多少个手指在触摸~
由题可知,是基于监听的事件处理机制,好像前面的点击事件是OnClickListener,文本内容
变化的监听器则是:TextWatcher,我们可以调用EditText.addTextChangedListener(mTextWatcher);
为EditText设置内容变化监听!
简单说下TextWatcher,实现该类需实现三个方法:
public void beforeTextChanged(CharSequence s, int start,int count, int after);
public void onTextChanged(CharSequence s, int start, int before, int count);
public void afterTextChanged(Editable s);
依次会在下述情况中触发:
1.内容变化前
2.内容变化中
3.内容变化后
这个也是一个很实用的需求,就是用户点击按钮后可让EditText中的密码可见或者不可见~
@Override
public void onClick(View view) {
if(flag == true){
edit_pawd.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
flag = false;
btnChange.setText("密码不可见");
}else{
edit_pawd.setTransformationMethod(PasswordTransformationMethod.getInstance());
flag = true;
btnChange.setText("密码可见");
}
}
});
densityDpi:屏幕密度
fontScale:当前用户设置的字体的缩放因子
hardKeyboardHidden:判断硬键盘是否可见,有两个可选值:HARDKEYBOARDHIDDEN_NO,HARDKEYBOARDHIDDEN_YES,分别是十六进制的0和1
keyboard:获取当前关联额键盘类型:该属性的返回值:KEYBOARD_12KEY(只有12个键的小键盘)、KEYBOARD_NOKEYS、KEYBOARD_QWERTY(普通键盘)
keyboardHidden:该属性返回一个boolean值用于标识当前键盘是否可用。该属性不仅会判断系统的硬件键盘,也会判断系统的软键盘(位于屏幕)。
locale:获取用户当前的语言环境
mcc:获取移动信号的国家码
mnc:获取移动信号的网络码
ps:国家代码和网络代码共同确定当前手机网络运营商
navigation:判断系统上方向导航设备的类型。该属性的返回值:NAVIGATION_NONAV(无导航)、 NAVIGATION_DPAD(DPAD导航)NAVIGATION_TRACKBALL(轨迹球导航)、NAVIGATION_WHEEL(滚轮导航)
orientation:获取系统屏幕的方向。该属性的返回值:ORIENTATION_LANDSCAPE(横向屏幕)、ORIENTATION_PORTRAIT(竖向屏幕)
screenHeightDp,screenWidthDp:屏幕可用高和宽,用dp表示
touchscreen:获取系统触摸屏的触摸方式。该属性的返回值:TOUCHSCREEN_NOTOUCH(无触摸屏)、TOUCHSCREEN_STYLUS(触摸笔式触摸屏)、TOUCHSCREEN_FINGER(接收手指的触摸屏)
1.相关概念
1)什么是多线程
答:先了解这几个名称:应用程序、进程、线程、多线程
应用程序(Application):为了完成特定任务,用某种语言编写的一组指令集和(一组静态代码)
进程(Process):运行中的程序,系统调度与资源分配的一个独立单位,操作系统会为每个进程分配一段内存空间,程序的依次动态执行,经历 代码加载->执行->执行完毕 的整个过程
线程(Thread):比进程更小的执行单元,每个进程可能有多个线程,线程需要放在一个进程中才能执行! 线程是由程序负责管理的!!!而进程则是由系统进行调度的!!!
多线程概念(Multithreading):并行地执行多条指令,将CPU的时间片按照调度算法,分配给各个线程,实际上是分时执行的,只是这个切换的时间很短,用户感觉是同时而已!
2)同步与异步的概念:
答:因为Android程序刚启动时,会同时启动一个对应的主线程(Main Thread),这个主线程主要负责处理
与UI相关的事件!有时我们也把他称作UI线程!而在Android App时我们必须遵守这个单线程模型的规则: Android
UI操作并不是线程安全的并且这些操作都需要在UI线程中执行! 假如我们在非UI线程中,比如在主线程中new
Thread()另外开辟一个线程,然后直接在里面修改UI控件的值; 此时会抛出下述异常:
android.view.ViewRoot$CalledFromWrongThreadException: Only the
original thread that created a view hierarchy can touch its views
另外,还有一点,如果我们把耗时的操作都放在UI线程中的话,如果UI线程超过5s没有响应用于请求,那么
这个时候会引发ANR(Application Not Responding)异常,就是应用无响应~ 最后还有一点就是:Android
4.0后禁止在UI线程中执行网络操作~不然会报: android.os.NetworkOnMainThreadException
2.AsyncTask全解析:
1)为什么要用AsyncTask?
答:我们可以用上述两种方法来完成我们的异步操作,加入要我们写的异步操作比较多,或者较为繁琐, 难道我们new Thread()然后用上述方法通知UI更新么?程序员都是比较喜欢偷懒的,既然官方给我 们提供了AsyncTask这个封装好的轻量级异步类,为什么不用呢?我们通过几十行的代码就可以完成 我们的异步操作,而且进度可控;相比起Handler,AsyncTask显得更加简单,快捷~当然,这只适合 简单的异步操作,另外,实际异步用的最多的地方就是网络操作,图片加载,数据传输等,AsyncTask 暂时可以满足初学者的需求,谢谢小应用,但是到了公司真正做项目以后,我们更多的使用第三发的 框架,比如Volley,OkHttp,android-async-http,XUtils等很多,后面进阶教程我们会选1-2个框架进行 学习,当然你可以自己找资料学习学习,但是掌握AsyncTask还是很有必要的!
2)AsyncTask的基本结构:
AsyncTask是一个抽象类,一般我们都会定义一个类继承AsyncTask然后重写相关方法~ 官方API:AsyncTask
构建AsyncTask子类的参数:
相关方法与执行流程:
注意事项:
1.手指触碰屏幕时,触发MotionEvent事件!
2.该事件被OnTouchListener监听,可在它的onTouch()方法中获得该MotionEvent对象!
3.通过GestureDetector转发MotionEvent对象给OnGestureListener
4.我们可以通过OnGestureListener获得该对象,然后获取相关信息,以及做相关处理!
文章是我在网上结合各种资料与自己学习Android过程中的心得,仅供刚开始学安卓的童鞋参考,也是为了自己学习写的。继续加油!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。