一、滑屏与点击事件的冲突,主要是onInterceptTouchEvent和onTouchEvent调用时序
touch事件在onInterceptTouchEvent()和onTouchEvent以及各个childView间的传递机制完全取决于onInterceptTouchEvent()和onTouchEvent()的返回值。并且,针对down事件处理的返回值直接影响到后续move和up事件的接收和传递。
关于返回值的问题,基本规则是:如果return true,那么表示该方法消费了此次事件,如果return false,那么表示该方法并未处理完全,该事件仍然需要以某种方式传递下去继续等待处理。
由于onInterceptTouchEvent()的机制比较复杂,上面的说明写的也比较复杂,总结一下,基本的规则是:
1. down事件首先会传递到onInterceptTouchEvent()方法。
2. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。
3. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。
4. 如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。
5. 如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。
二、切换动画效果的展示,主要是线程与动画
三、锁键盘
//重写View的onKeyDown来实现监控/拦截/屏蔽返回键、菜单键、音量调节键以及打/挂电话键
publicboolean onKeyDown(int keyCode, KeyEvent event)
{
switch (keyCode)
{
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_CALL:
case KeyEvent.KEYCODE_ENDCALL:
case KeyEvent.KEYCODE_MENU:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
returntrue;
}
returnsuper.onKeyDown(keyCode, event);
}
//由于Home键为系统键,onKeyDown()中不能捕获,需要重写onAttachedToWindow()来监控/拦截系统Home键
publicvoid onAttachedToWindow()
{
this.getWindow().setType
(WindowManager.LayoutParams.TYPE_KEYGUARD);
super.onAttachedToWindow();
}
四、拍照上传,实现了SurfaceHolder.Callback接口(在SurfaceHolder.Callback接口的surfaceCreated()的方法中初始化,在surfaceDestroyed()方法中释放摄像头资源)和Camera.PictureCallback接口(onPictureTaken()方法中保存图片数据到指定文件里)。
1.检测手机是否有前置摄像头
for (int i = 0; i < Camera.getNumberOfCameras(); i++)
{
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_FRONT)
{
mCamera = Camera.open(i);
mCamera.setPreviewDisplay(mSurfaceHolder);
}
}
//获取摄像头参数
Camera.Parameters mParameters = mCamera.getParameters();
//设置图片格式
mParameters.setPictureFormat(PixelFormat.JPEG);
mCamera.setParameters(mParameters);
//开始预览
mCamera.startPreview();
2. 拍照回调
publicvoid onPictureTaken(byte[] data, Camera camera)
{
Bitmap mBitmap = BitmapFactory.decodeByteArray
(data, 0, data.length);
//文件路径和文件名
File pictureFile = new File(
Environment.getExternalStorageDirectory(), "camera.jpg");
FileOutputStream mFileOutputStream = new FileOutputStream(
pictureFile);
mBitmap.compress(Bitmap.CompressFormat.JPEG,75,
mFileOutputStream);
}
3.拍照后将获取文件以流的方式上传
/**
* 提交参数里有文件的数据
* @param url 服务器地址
* @param file 照片文件
* @return服务器返回照片保存路径
* @throws Exception
*/
public String uploadSubmit(String url, File file) throws Exception
{
HttpPost post = new HttpPost(url);
MultipartEntity entity = new MultipartEntity();
// 添加文件参数
if (file != null && file.exists())
{
entity.addPart("file", new FileBody(file));
}
post.setEntity(entity);
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(post);
int stateCode = response.getStatusLine().getStatusCode();
StringBuffer sb = new StringBuffer();
if (stateCode == HttpStatus.SC_OK)
{
HttpEntity result = response.getEntity();
if (result != null)
{
InputStream is = result.getContent();
BufferedReader br = new BufferedReader(
new InputStreamReader(is));
String tempLine;
while ((tempLine = br.readLine()) != null)
{
sb.append(tempLine);
}
}
}
post.abort();
return sb.toString();
}
五、其他
1.LinearLayout对onTouchEvent事件无作用
解决方案:使mainLayout获取焦点====》 mainLayout.setClickable(true);
2.ListView获取不了焦点
解决方案:在适配器中添加
adapterView.setFocusable(true);
adapterView.setFocusableInTouchMode(true);
adapterView.requestFocus();
3.linearlayout的背景适应不了定义高度:
解决方案:可能跟分辨率有关,试着将图片放高、中、低分辨率的文件夹中
4.获取SD卡的路径:Environment.getExternalStorageDirectory()
5. 获取本机电话号码
TelephonyManager tm = (TelephonyManager)this.getSystemService
(Context.TELEPHONY_SERVICE);
String phoneNumber = tm.getLine1Number();
//********************************************************************
扩展TelephonyManager
获取SIM卡信息。在SIM卡中并没有保存用户的手机,区分每一张SIM是通过IMSI码。在运营商的数据库中存在手机号码和IMSI码的映射,所以手机是通过发送IMSI码到运营商的一端,获得自己的手机号码。
TelephonyManager tm = (TelephonyManager)this.getSystemService
(Context.TELEPHONY_SERVICE);
//获取手机号码一般是为空的,因为运营商没有基本没有把本机电话保存在SIM卡中 标识每一张SIM卡是通过IMSI码(tm.getSubscriberId()).
//在运营商的数据库表中有IMSI码与电话号码的映射。所以,手机是通过发送IMSI码到运营商一端,才获得自己的手机号码
String phonenumber = tm.getLine1Number();
//获得每一张电话卡的唯一标识IMSI码
String subscriberid = tm.getSubscriberId();
//获取网络的类型
int phonetype = tm.getPhoneType();
String phonetype_str = "null";
switch(phonetype){
case TelephonyManager.PHONE_TYPE_GSM:
phonetype_str ="GSM网络";
break;
case TelephonyManager.PHONE_TYPE_CDMA:
phonetype_str ="CDMA网络";
break;
case TelephonyManager.PHONE_TYPE_NONE:
phonetype_str ="未识别网络";
break;
}
//获取手机状态
int simstate = tm.getSimState();
String simstatestr = "null";
switch(simstate ){
case TelephonyManager.SIM_STATE_UNKNOWN:
simstatestr = "未知状态";
break;
case TelephonyManager.SIM_STATE_ABSENT:
simstatestr = "未插卡";
break;
case TelephonyManager.SIM_STATE_PIN_REQUIRED:
simstatestr = "需要PIN密码解锁";
break;
case TelephonyManager.SIM_STATE_PUK_REQUIRED:
simstatestr = "需要PUK密码解锁";
break;
case TelephonyManager.SIM_STATE_READY:
simstatestr = "就绪";
break;
case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
simstatestr = "SIM已经被锁住";
break;
}
读取这些数据需要权限
<uses-permission android:name="android.permission.READ_PHONE_STATE">
</uses-permission>
****************************************************************//
6.发送短信
//信息管理对象
SmsManager smsManager = SmsManager.getDefault();
PendingIntent intent = PendingIntent.getBroadcast
(context, 0, new Intent(),0);
// 按照一条短信,最大容量拆分成多条短信
List<String> divideContents = smsManager.divideMessage("手机IMSI码为" + safedSubscriberid + " 已被更换SIM卡,更换的SIM卡IMSI码为:" + subscriberid);
for (String text : divideContents)
{smsManager.sendTextMessage
(<参数1>, <参数2>, <参数3>, <参数4>, <参数5>);}
-- 参数1: destinationAddress:目标电话号码
-- 参数2: scAddress:短信中心号码,测试可以不填
-- 参数3: text: 短信内容
-- 参数4: sentIntent:发送 -->中国移动 --> 中国移动发送失败 --> 返回发送成功或失败信号 --> 后续处理 即,这个意图包装了短信发送状态的信息
-- 参数5: deliveryIntent: 发送 -->中国移动 --> 中国移动发送成功 --> 返回对方是否收到这个信息 --> 后续处理 即:这个意图包装了短信是否被对方收到的状态信息(供应商已经发送成功,但是对方没有收到)。
声明短信发送权限
<uses-permission android:name="android.permission.SEND_SMS"/>
//*****************************************************************************
扩展SmsManager之 读取短信内容
接收短信时发送的广播
<receiver android:name=".ReceiveSMSReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
在接收某些广播的时候需要权限,例如接收短信的广播就需要
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
当短信到来的时候,系统会将短信的内容封装成pdu的格式,然后放到intent里面。所以要获得短信的内容,就通过intent,将puds拿出来就可以了,它返回的是Object数组
Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
创建一个二维字节数组
byte[][] pduObjs = new byte[messages.length][];
for (int i = 0; i < messages.length; i++){
pduObjs[i] = (byte[]) messages[i];
}
byte[][] pdus = new byte[pduObjs.length][];
int pduCount = pdus.length;
SmsMessage[] msgs = new SmsMessage[pduCount];
for (int i = 0; i < pduCount; i++){
pdus[i] = pduObjs[i];
msgs[i] = SmsMessage.createFromPdu(pdus[i]);
}
return msgs;
}
一条短信就是一个SmsMessage ,这个SmsMessage可以通过一个byte[]来创建
*************************************************************************//
7. 关于SharedPreferences
在android平台下用于保存数据有三种方式:
1、SQLite 2、SharedPreferences 3、File
SharedPreferences是将数据保存在一个xml文件中,并且是以Map的形式保存,一个Key对应一个Value,但获取某一个Key的时候,都会有一个默认值,这个默认值是在xml不存在这个key值的时候使用
获得SharedPreferences是通过上下文(Context)中的getSharedPreferences方法获得。SharedPreferences sp = this.getSharedPreferences("data",
MODE_WORLD_READABLE);
第一个参数是指定xml文件的名字,当不存在的时候就会创建它。
第二个参数是获得这个SharedPreferences的模式,一共有四种模式:
MODE_APPEND、MODE_PRIVATE、MODE_WORLD_READABLE 、MODE_WORLD_WRITEABLE
从SharedPreferences中取值是通过sp.getXXX的方式可以获得对应key的值,在getXXX的时候,需要指定一个默认的值,当key值不存在的时候使用。
往ShaSharedPreferences中设值需要用到Editor
Editor editor = sp.edit();
获得了Editor之后,才能对SharedPreferences进行写
editor.putXXX(“key”,value)
最后需要注意的一点是别忘了commit
Xml文件存放的位置位于data/data/包名/shared_prefs/xxx.xml
8.java监听者模式
9. 触摸ListView背景会变黑
出现原因:如果不使用手机上下按键的时候,直接用触摸拖动视图的方式,会发现ListView的背景一片黑色,而且所有被选中的文字都变成一片漆黑。
其实这个问题发生的原因在于ListView存在缓存颜色机制,
解决方案:可以通过设定缓存颜色为透明的方法来解决这个问题:
A、通过布局属性来设定(ListView的属性中直接定义)
android:cacheColorHint=”#00000000″
B、在代码中直接设定
listView.setCacheColorHint(Color.TRANSPARENT)