一:文本的颜色选择器:
在res目录下面创建color文件夹,在color文件夹下面创建font_style_colors.xml文件<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="#FFFFFF" />
<item android:state_focused="true" android:color="#FFFFFF" />
<item android:state_pressed="true" android:color="#FFFFFF" />
<item android:color="#666666"></item>
</selector>
在布局文件中使用字体颜色选择器
<Button
android:id="@+id/bt_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/feedback_selector"
android:text="确定"
android:textColor="@color/font_style_colors" />
二、关于Calener的比较
calendar的compareto测试时出现了两个时间相等,但比较结果不是我断言的,经高人指点,这才明白,原来calendar.set(year,month,day,hour,min,sec)没有设置ccalendar.millisecond,需要设置calendar.millisecond为0:
例如
calendar now=calendar.getinstance();
now.set(2008,11,1,0,0,0);now.set(calendar.millisecond,0);
calendar start = calendar.getinstance();
start.set(2008, 11, 1, 0, 0, 0);
start.set(calendar.millisecond, 0);
if(start.compareto(now) == 0){
system.out.println("success");
}
这样设置的时间才是精确的2008-12-1 0:00:00,两个时间对比的时候才能得到我想要的结果!
上面那个有点不靠谱,自己写了一个工具方法:
/**
* 就是先格式化一下时间,将后面的秒数干掉,然后又变成时间,最后比较
* @param localDate
* @return
*/
public static int compareData(Date localDate) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Date data = Calendar.getInstance().getTime();
String currentString = df.format(data);
String localDateString = df.format(localDate);
try {
Date dt1 = df.parse(localDateString);
Date dt2 = df.parse(currentString);
if (dt1.getTime() > dt2.getTime()) {
System.out.println("dt1 在dt2后");
return 1;
} else if (dt1.getTime() < dt2.getTime()) {
System.out.println("dt1在dt2前");
return -1;
} else {
return 0;
}
} catch (Exception e) {
e.printStackTrace();
}
return Integer.MAX_VALUE;
}
三、干掉项目中标题栏
1、 针对一个ActivityrequestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏
2、 去掉整个应用的标题栏
<application
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar">
3、 在res/values目录下面新建一个style.xml的文件:有经验的开发者最喜欢的方法,因为它把功能分开的;对于后期的维护非常方便。
style.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<style name="concealTitle">
<item name="android:windowNoTitle">true</item>
</style>
</resources>
在AndroidManifest.xml文件中引用
<application
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@style/concealTitle">
四:键盘覆盖掉输入法的问题(不太好使)
不希望遮挡设置activity属性android:windowSoftInputMode="adjustPan"希望动态调整高度android:windowSoftInputMode="adjustResize"
五:学会使用ExpandableListView这个类
1、ExpandableListView要使用的适配器类private class MyAdapter extends BaseExpandableListAdapter {
/**
* 返回有多少个分组 先被调用.
*/
public int getGroupCount() {
if (groupItems == null) {
groupItems = CommonNumDao.getGroupInfos();
}
return groupItems.size();
}
/**
* 返回每个分组里面有多少个孩子
*/
public int getChildrenCount(int groupPosition) {
List<String> childInfos;
if (childrenCaches.containsKey(groupPosition)) {
childInfos = childrenCaches.get(groupPosition);
} else {
childInfos = CommonNumDao
.getChildrenInfosByGroupPostion(groupPosition);
childrenCaches.put(groupPosition, childInfos);
}
return childInfos.size();
}
public Object getGroup(int groupPosition) {
return null;
}
public Object getChild(int groupPosition, int childPosition) {
return null;
}
public long getGroupId(int groupPosition) {
return groupPosition;
}
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
public boolean hasStableIds() {
return false;
}
/**
* 返回某个分组显示的view对象.
*/
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
TextView tv ;
if(convertView==null){
tv = new TextView(getApplicationContext());
}else{
tv = (TextView) convertView;
}
tv.setTextSize(28);
tv.setTextColor(Color.RED);
// tv.setText(" " + CommonNumDao.getGroupName(groupPosition));
tv.setText(" " + groupItems.get(groupPosition)); // 改成了查询内存
return tv;
}
/**
* 返回某个分组的某个孩子的view对象.
*/
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
TextView tv ;
if(convertView==null){
tv = new TextView(getApplicationContext());
}else{
tv = (TextView) convertView;
}
tv.setTextSize(20);
tv.setTextColor(Color.BLACK);
// tv.setText(CommonNumDao.getChildInfoByPosition(groupPosition,
// childPosition));
tv.setText(childrenCaches.get(groupPosition).get(childPosition));
return tv;
}
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
2、修改ExpandableListView前面的箭头标记:
分两个步骤:
①:写背景图片选择器
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 在ExpandableListView展开的时候,显示的图片 -->
<item android:drawable="@drawable/expend_f" android:state_expanded="true"/>
<!-- 在ExpandableListView默认的情况下(没有展开),显示的图片 -->
<item android:drawable="@drawable/expand_d" />
</selector>
②:在代码中添加如下代码
ExpandableListView.setGroupIndicator(getResources().getDrawable(R.drawable.expandlist_selector));
3、干掉ExpandableListView拉动时的颜色。默认为黑色
android:cacheColorHint="@android:color/transparent"
4、干掉条目点击时的颜色,换成自己的颜色
android:listSelector="@drawable/feedback_selector"
六、merge标签和include标签
1.当LayoutInflater遇到<merge/>标签时,它会跳过它,并将<merge />内的元素添加到<merge />的父元素里。<merge/>只能作为XML布局的根标签使用,只能替换<FrameLayout/>
当Inflate以<merge />开头的布局文件时,必须指定一个父ViewGroup,并且必须设定attachToRoot为true。参看LayoutInflater.inflate(int resource, ViewGroup root, boolean attachToRoot)。
2. include标签内不能设置RelativeLayout属性,如android:layout_alignParentBottom,因为不起作用
include标签内设置id属性后(android:id),其引用的布局layout内的id属性就不起作用了,怀疑是其引用的layout外层包裹了一层include标签或者是覆盖了其内的属性id
如果没有include标签,所有布局代码都写在一个xml文件中,界面会显得很冗余,可读性很差。而且界面加载的时候是按照顺序加载的,前面的布局不能调用其后面的布局id。而采用include后,一个include中可以引用其后的include中的布局id属性
七、ScrollView嵌套GridView,加载完成后默认不显示顶部
强调:就算ScrollView里面没有嵌套GridView和ListView,只要文本超出了内容,一般都会显示最下面的东西。这个时候,我们得想办法让用户可以看到上面的信息。解决方式:
在ScrollView中嵌套了GridView或者ListView,在第一次activity启动后,会显示顶部位置。当activity再次唤醒的时候,就默认显示GridView了,并不是ScrollView的顶部位置。
解决这个问题的办法就是在Activity的OnResume方法中添加一段代码即可
protected void onResume() {
scrollView.smoothScrollTo(0, 0);
super.onResume();
}
八、关于在ScrollView中嵌套ListView或者GridView。导致ListView、GridView没有滑动效果
按照android的标准,ScrollView中是不能嵌套具有滑动特性的View的,但是有时如果设计真的有这样做的需要,或者为了更方便简单的实现外观(比如在外在的大布局需要有滑动的特性,并且内部有类似于List的UI结构,那么ListView + Adpater的方式来实现里面的效果就很方便,算是违规抄近道的一种
方式吧),有时就会不得不采用这种怪异的组合方式。先说下这种方式如果不做特殊处理时会出现的冲突和问题:
1,在SrollView中嵌套ListView,ListView的显示会有问题,只显示一行或显示效果与预期不同,这是因为android禁止这样使用,放入ScrollView中的ListView的高度是无法计算的。
2,嵌套中的子ListView和GridvIew是无法滑动的,因为子控件的滑动事件会被外面的ScrollView吃掉,如果想让子控件可以滑动,只能强行的截取滑动的相关事件了。
言归正传,嵌套的解决方案:1,第一种方案,也是我比较推荐的方案,就是重写ListView与GridView,让其失去滑动特性:
package com.perfect.xiaoao.all.ui;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.GridView;
public class NoScrollGridView extends GridView{
public NoScrollGridView(Context context, AttributeSet attrs){
super(context, attrs);
}
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int mExpandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, mExpandSpec);
}
}
package com.perfect.xiaoao.all.ui;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
/**
* Created by IntelliJ IDEA.
* User: zhUser
* Date: 13-1-24
* Time: 下午6:53
*/
public class NoScrollListView extends ListView{
public NoScrollListView(Context context, AttributeSet attrs){
super(context, attrs);
}
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int mExpandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, mExpandSpec);
}
}
2,第二种方案,也是网上流行的一种解决办法,人工计算子控件的尺寸,解决办法:
在listview.setAdapter()之后调用Utility.setListViewHeightBasedOnChilren(listview)就Okay 了。
public class Utility {
public static void setListViewHeightBasedOnChildren(ListView listView) {
//获取ListView对应的Adapter
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
for (int i = 0, len = listAdapter.getCount(); i < len; i++) { //listAdapter.getCount()返回数据项的数目
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0); //计算子项View 的宽高
totalHeight += listItem.getMeasuredHeight(); //统计所有子项的总高度
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
//listView.getDividerHeight()获取子项间分隔符占用的高度
//params.height最后得到整个ListView完整显示需要的高度
listView.setLayoutParams(params);
}
}
原理就是:设置完ListView的Adapter后,根据ListView的子项目重新计算ListView的高度,然后把高度再作为LayoutParams设置给ListView,这样它的高度就正确了,通过人工算取控件的应有高度,再设置给ListView
注意:这个方案中子ListView的每个Item必须是LinearLayout,不能是其他的,因为其他的Layout(如RelativeLayout)没有重写onMeasure(),所以会在onMeasure()时抛出异常。
最后,建议大家还是少用这样的设计,毕竟这种方式是不标准与不规范的。
九、android javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
博客地址:http://lanyan-lan.iteye.com/blog/1522370最近做项目,界面有选择使用SSL登陆或非SSL登陆,发现本来可以登陆的程序刷系统或者换机器登陆不了,痛苦了好一会儿,解决了,如下为解决方案,项目中用的挺帅的
第一步:编写SSLSocketFactoryEx,以代替原有的SSLSocketFactory,代码如下
import org.apache.http.conn.ssl.SSLSocketFactory;
public class SSLSocketFactoryEx extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public SSLSocketFactoryEx(KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] chain, String authType)
throws java.security.cert.CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] chain, String authType)
throws java.security.cert.CertificateException {
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port,
autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}
第二步:编写新的HttpClient getNewHttpClient来代替原有DefaultHttpClient,代码如下:
public static HttpClient getNewHttpClient() {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
return new DefaultHttpClient();
}
}
第三步;接着在项目里把所有获得HttpClient实例通过DefaultHttpClient,都改成从
getNewHttpClient获取
//HttpClient hc = new DefaultHttpClient(httpParams);
//modified by lucky.lan@2012/05/10
HttpClient hc = ConnectionManager.getNewHttpClient() ;
10、android布局文件中scrollview中android:fillviewpoint="true"是什么意思?
这玩意儿在ScrollView中用处比较大表明这ScrollView是否应该伸展其内容的高度来填补视图。 true则表示自动拉伸填补,false则不拉伸,默认为false,也就是说不拉伸内容,所以你一般看到的ScrollView在内容超过固定高度就会有滚动效果。
11、android sqlite批量插入数据速度解决方案(不一定非得将整个数据库加载到应用下面)
最近在做android项目的时候遇到一个问题,应用程序初始化时需要批量的向sqlite中插入大量数,导致应用启动过慢。android使用的是sqlite数据库,sqlite是比较轻量级的数据库,在Google了之后发现,sqlite事务处理的问题,在sqlite插入数据的时候默认一条语句就是一个事务,
有多少条数据就有多少次磁盘操作。我的应用初始5000条记录也就是要5000次读写磁盘操作。
解决方法:
添加事务处理,把5000条插入作为一个事务
SQLiteDatabase.beginTransaction(); //手动设置开始事务
//数据插入操作循环
SQLiteDatabase.setTransactionSuccessful(); //设置事务处理成功,不设置会自动回滚不提交
SQLiteDatabase.endTransaction(); //处理完成
12、android中怎样判断ListView滑动到最后一条?
lv_refresh.setOnScrollListener(new OnScrollListener(){@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (view.getLastVisiblePosition() == view.getCount() - 1) {
//执行异步刷新的操作
new AsyncTask().execute();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {
}
});
13、Android中两张图片合并
private Bitmap mergeBitmap(Bitmap firstBitmap, Bitmap secondBitmap) {Bitmap bitmap = Bitmap.createBitmap(firstBitmap.getWidth(), firstBitmap.getHeight(),
firstBitmap.getConfig());
Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(firstBitmap, new Matrix(), null);
canvas.drawBitmap(secondBitmap, 0, 0, null);
return bitmap;
}
14、调起键盘,而且还希望监听调起键盘的监听事件
先添加监听事件,然后再利用计时器调起键盘et_search.setOnKeyListener(new OnKeyListener(){
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_ENTER&& event.getAction() == KeyEvent.ACTION_UP){
imm.hideSoftInputFromWindow(et_search.getWindowToken(), 0);
searchCategory();
return true;
}
return false;
}
});
Timer timer = new Timer();
timer.schedule(new TimerTask(){
@Override
public void run() {
imm = (InputMethodManager) et_search.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
}
}, 200);
在默认情况下,被我们代码调起来的键盘是不会关闭的,需要我们手工关闭,此时又要关闭键盘
点击应用中的后退按钮
if(imm!=null&&imm.isActive()){
// imm.hideSoftInputFromInputMethod(et_search.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
//下面这个起作用
imm.hideSoftInputFromWindow(et_search.getWindowToken(), 0);
}
要注意一件事儿,InputMethodManager.hideSoftInputFromWindow和hideSoftInputFromInputMethod是不一样的
16、在android原生系统中,默认情况下Dialog打开之后,点击Dialog外围,Dialog是不会消失的,但是有的手机不会这样,比如说小米手机
这个时候,我们就应该添加一个方法,让它不消失。dialog.setCanceledOnTouchOutside(false);
在AlertDialog是Dialog的子类,但是AlertDialog没有这个方法,我们只需要将其变成Dialog即可
17、怎样调用系统的闹铃的铃声
问题出现场景:做一个android小应用(类似闹钟),我想在设定的事件触发后响铃提醒用户,不知道能否调用系统中原有的闹钟铃声。(思路一:)android源码中有个便签的应用程序,你可以去看看代码!
(思路二:)
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM),会得到默认的闹铃铃声
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(this, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE));
mp.prepare();
mp.start();
这个是播放默认铃音的一段代码,闹铃只要改下Type就行了
18、问题:怎样让自己的Activity中的标题栏不受挤压
最近项目里有类似微信聊天界面需要我去写,要动态显示最新的数据,效果和微信基本一样。有个问题困扰我一晚上,每次进入Activity后,EditText自动获得焦点弹出软键盘,键盘遮挡listView,使得无法显示最后一条消息。我在edittext点击事件中也设定了,listView.setSelection,
选中最后一条数据,可是每次需要点击两下才会显示最新消息,最后在windowSoftInputMode设置了N种组合还是不行。到中午修改Bug,莫名其妙的把acitivity设置成了全屏,
这样每次进入acitivity,整个布局都将被上移,其中自定义的Title每次都被挤出屏幕,此奥,这样……我又一边边找错误,
终于发现原来我把屏幕设置为了全屏,所以设置inputMode为adjustResize木有反应,Tittle依然被挤出。
最后发现,ListView有一属性,android:transcriptMode="normal" 设置过后,再配合adjustResize这样每次进入界面后,效果和微信一模一样了,listView被压缩,
tittle也不会移出屏幕,并且listView显示最新一条数据。哈哈,终于大功告成~~~~~另外android:stackFromBottom="true"时,如果是动态加载数据,
listView每次回从最下面开始加载,这样listVIew上面一片空白,效果不好。
①:在menifest中的activity界面添加
android:windowSoftInputMode="stateHidden|adjustResize"
②:在ListView中添加transcriptMode属性,并且设置为normal
【A】stateUnspecified:软键盘的状态并没有指定,系统将选择一个合适的状态或依赖于主题的设置
【B】stateUnchanged:当这个activity出现时,软键盘将一直保持在上一个activity里的状态,无论是隐藏还是显示
【C】stateHidden:用户选择activity时,软键盘总是被隐藏
【D】stateAlwaysHidden:当该Activity主窗口获取焦点时,软键盘也总是被隐藏的
【E】stateVisible:软键盘通常是可见的
【F】stateAlwaysVisible:用户选择activity时,软键盘总是显示的状态
【G】adjustUnspecified:默认设置,通常由系统自行决定是隐藏还是显示
【H】adjustResize:该Activity总是调整屏幕的大小以便留出软键盘的空间
【I】adjustPan:当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分
同样的问题:
http://www.eoeandroid.com/thread-227827-1-1.html
[Android UI界面] windowSoftInputMode怎样设置才能不会把整个activity向上顶出呢?
这是我的布局,在点最下方的edittext控件,输入法会把整个activity向上顶出,如果我不想把最上的那个title向上推那要怎么办呢?
manifest:
<activity
android:name=".FriendMessageContentActivity"
android:configChanges="keyboardHidden|orientation"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:windowSoftInputMode="adjustPan" />
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background"
android:orientation="vertical" >
<RelativeLayout
android:id="@+id/top_pic"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="@drawable/alltitle"
android:orientation="horizontal" >
<Button
android:id="@+id/btn_back"
style="@style/titlebuttontext"
android:layout_width="40.0dip"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="6.0dip"
android:background="@drawable/all_title_button"
android:gravity="center"
android:visibility="gone" />
<LinearLayout
android:id="@+id/title_ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:orientation="horizontal" >
<TextView
android:id="@+id/title_tv"
style="@style/titletext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />
<ImageView
android:id="@+id/arrow_tip_iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
</LinearLayout>
<Button
android:id="@+id/btn_next"
style="@style/titlebuttontext"
android:layout_width="40.0dip"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="6.0dip"
android:background="@drawable/all_title_button"
android:gravity="center"
android:visibility="gone" />
</RelativeLayout>
<ListView
android:id="@+id/iolist_lv"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="@+id/messageinput_rl"
android:layout_below="@+id/top_pic"
android:cacheColorHint="#00000000"
android:clickable="true"
android:fadeScrollbars="true"
android:fadingEdge="none"
android:fastScrollEnabled="true"
android:listSelector="@drawable/list_selector"
android:focusable="true" />
<RelativeLayout
android:id="@+id/messageinput_rl"
android:layout_width="fill_parent"
android:layout_height="60.0dip"
android:layout_alignParentBottom="true"
android:background="@drawable/tablecell_highlight" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</LinearLayout>
<EditText
android:id="@+id/messagecontent_et"
android:layout_width="fill_parent"
android:layout_height="40.0dip"
android:layout_centerVertical="true"
android:layout_marginLeft="10.0dip"
android:layout_marginRight="10.0dip"
android:layout_toLeftOf="@+id/send_bt"
android:background="@drawable/all_base_bg"
android:paddingLeft="4.0dip"
android:paddingRight="4.0dip"/>
<Button
android:id="@+id/send_bt"
android:layout_width="wrap_content"
android:layout_height="40.0dip"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="6.0dip"
android:text="@string/sendmessage" />
</RelativeLayout>
</RelativeLayout>
解决办法:
就在最下边的RelativeLayout上边加上
<ScrollView
android:layout_width="fill_parent"
android:layout_height="0dip"/>
这样就可以的了。
19、友盟社会化分享
选中产品---组件---社会化分享---设置20、关于ActionBar的解决方式
http://blog.csdn.net/fireofstar/article/details/7378824操作步骤:
①先定义menu(注意showAsAction)在res/menu/main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:showAsAction="never"
android:title="@string/action_settings"/>
<item
android:id="@+id/action_add"
android:icon="@drawable/ic_action_refresh"
android:showAsAction="always"
android:title="action_add"/>
<item
android:id="@+id/action_save"
android:icon="@drawable/ic_action_search"
android:showAsAction="ifRoom|withText"
android:title="action_save"/>
<item
android:id="@+id/action_delete"
android:icon="@drawable/ic_action_share_selector"
android:showAsAction="ifRoom|withText"
android:title="action_delete"/>
</menu>
②在Activity中加载,并且添加监听
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_add:
Toast.makeText(this, "action_add", 0).show();
break;
case R.id.action_save:
Toast.makeText(this, "action_save", 0).show();
break;
case R.id.action_delete:
Toast.makeText(this, "action_delete", 0).show();
break;
}
return super.onOptionsItemSelected(item);
}
③修改ActionBar的样式(在values-v14中创建actionbar_style.xml)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- the theme applied to the application or activity -->
<style name="CustomActivityTheme" parent="@android:style/Theme.Holo">
<item name="android:actionBarStyle">@style/MyActionBar</item>
<!-- other activity and action bar styles here -->
</style>
<!-- style for the action bar backgrounds -->
<style name="MyActionBar" parent="@android:style/Widget.Holo.ActionBar">
<item name="android:background">@drawable/daohang</item>
<item name="android:backgroundStacked">@drawable/click_item_1</item>
<item name="android:backgroundSplit">@drawable/click_item_3</item>
</style>
</resources>
④在清单中Activity或者application节点引用样式:
<activity
android:theme="@style/CustomActivityTheme"
21、关于Java设计模式中的简单工厂、工厂方法、抽象工厂的区别:
博客地址:http://blog.chinaunix.net/uid-25979788-id-3199524.html简单工厂、工厂方法,抽象工厂都属于设计模式中的创建型模式。主要功能是:帮我们将对象的实例化部分抽取出来,优化系统架构,增强系统拓展性
简单工厂:工厂类一般使用静态方法,通过接收参数的不同,返回不同对象实例
缺点:不修改代码是无法进行拓展的
工厂方法:针对每一种产品提供一个工厂类。通过不同工厂创建不同实例。
优点:在同一等级结构支持增加任意产品
抽象工厂:是应对产品族概念的。每个汽车公司可能要同时生产轿车,货车,客车,那么每一个工厂都要有创建轿车,货车和客车的方法
缺点:应对产品族概念而生,增加新的产品线很容易,但是无法增加新的产品
小结
★工厂模式中,重要的是工厂类,而不是产品类。产品类可以是多种形式,多层继承或者是单个类都是可以的。但要明确的,工厂模式的接口只会返回一种
类型的实例,这是在设计产品类的时候需要注意的,最好是有父类或者共同实现的接口。
★使用工厂模式,返回的实例一定是工厂创建的,而不是从其他对象中获取的。
★工厂模式返回的实例可以不是新创建的,返回由工厂创建好的实例也是可以的。
区别
简单工厂 :用来生产同一等级结构中的任意产品。(对于增加新的产品,无能为力)
工厂模式 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)
以上三种工厂方法在等级结构和产品族这两个方向上的支持程度不同。所以要根据情况考虑应该使用哪种方法。
22、关于监听PopupWindow的键盘事件和dismiss事件
PopupWindow在设置setFocusable后监听返回键盘事件PopupWindow在设置了焦点之后,那么这个弹出窗口就是当前操作的窗口,如果想要在此时响应按键事件,就需要在PopupWindow上注册键盘事件来响应。
1、监听dismiss事件:但是PopupWindow好像只有一个OnDismissListener,怎么来注册键盘事件监听呢?
2、监听按键事件:可以利用PopupWindow里的最外层View,对该子View监听键盘事件setOnKeyListener即可。
示例代码:
popupwindow.setBackgroundDrawable(new BitmapDrawable());
popupwindow.setFocusable(true);
popupwindow.setFocusableInTouchMode(true);
childrenView.setOnKeyListener(new OnKeyListener()
{
@Override
public boolean onKey(View v, int keyCode, KeyEvent event)
{
// TODO Auto-generated method stub
if (keyCode == KeyEvent.KEYCODE_BACK)
{
Log.v("keyCode", "/" + keyCode);
if(popupwindow != null) {
popupwindow.dismiss();
popupwindow = null;
}
}
return false;
}
});
23、android检测软键盘的弹起与隐藏
方法一:android开发者可能会遇到需要检测软键盘的弹出和隐藏问题,这里给出一个实用而又经典的方法。
下面谈谈实现原理:
使用自定义布局,页面布局中包含ScrollVIew,在软键盘弹起后,布局的高度会发生改变,根据布局的高度来判断软键盘的状态。
package com.ransj.keyboard;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.RelativeLayout;
public class KeyboardLayout extends RelativeLayout {
private static final String TAG = KeyboardLayout.class.getSimpleName();
public static final byte KEYBOARD_STATE_SHOW = -3;
public static final byte KEYBOARD_STATE_HIDE = -2;
public static final byte KEYBOARD_STATE_INIT = -1;
private boolean mHasInit;
private boolean mHasKeybord;
private int mHeight;
private onKybdsChangeListener mListener;
public KeyboardLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public KeyboardLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public KeyboardLayout(Context context) {
super(context);
}
/**
* set keyboard state listener
*/
public void setOnkbdStateListener(onKybdsChangeListener listener){
mListener = listener;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (!mHasInit) {
mHasInit = true;
mHeight = b;
if (mListener != null) {
mListener.onKeyBoardStateChange(KEYBOARD_STATE_INIT);
}
} else {
mHeight = mHeight < b ? b : mHeight;
}
if (mHasInit && mHeight > b) {
mHasKeybord = true;
if (mListener != null) {
mListener.onKeyBoardStateChange(KEYBOARD_STATE_SHOW);
}
Log.w(TAG, "show keyboard.......");
//软键盘弹出
}
if (mHasInit && mHasKeybord && mHeight == b) {
mHasKeybord = false;
if (mListener != null) {
mListener.onKeyBoardStateChange(KEYBOARD_STATE_HIDE);
}
Log.w(TAG, "hide keyboard.......");
//软键盘隐藏
}
}
public interface onKybdsChangeListener{
public void onKeyBoardStateChange(int state);
}
}
这个是自定义的布局,自定义布局可以继承各种常见布局。自定义布局有键盘状态改变监听器,可以通过注册监听器来监听软键盘状态。
<?xml version="1.0" encoding="utf-8"?>
<com.ransj.keyboard.KeyboardLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/keyboardLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:fillViewport="true" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/testone_tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#000000"
android:gravity="center"
android:text="软件盘弹起,我将消失!软键盘隐藏,我将回来!"
android:layout_weight="1.0"
android:textColor="#00ff00"
android:textStyle="bold" />
<EditText
android:id="@+id/testone_et"
android:layout_width="fill_parent"
android:layout_height="wrap_content"></EditText>
</LinearLayout>
</ScrollView>
</com.ransj.keyboard.KeyboardLayout>
方法二
Android soft (virtual) keyboard listener
If you use Evernote android app you might have noticed, that when, on a login screen, soft keyboard gets shown (to type password or username) the layout doesn't just scale, or scrolls. It changes (for example Evernotes logo is hidden).
Unfortunately, android api doesn't provide you with the specific tools to listen for a moment, when soft keyboard gets shown, or hidden. But there is a way (dirty hack) to assume that the keyboards state was changed.
We can guess it by listening measure changes in layout.
To do it, first, we need to make our layout to resize and scale instaed of scroll. Add android:windowSoftInputMode="adjustResize" parameter to your activity in manifest.xml. This way, when soft keyboard is called, content will be resized instead of scrolled.
Next step is to actually listen for this resizing. And again, there is a catch. There is no such thing as OnMeasureChangedListener, so the only way is to extend the container layout and do it inside. As an example I extended LinearLayout, and this is what I've got:
public class MyLayout extends LinearLayout {
public MyLayout(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public MyLayout(Context context) {
super(context);
}
private OnSoftKeyboardListener onSoftKeyboardListener;
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
if (onSoftKeyboardListener != null) {
final int newSpec = MeasureSpec.getSize(heightMeasureSpec);
final int oldSpec = getMeasuredHeight();
// If layout became smaller, that means something forced it to resize. Probably soft keyboard :)
if (oldSpec > newSpec){
onSoftKeyboardListener.onShown();
} else {
onSoftKeyboardListener.onHidden();
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public final void setOnSoftKeyboardListener(final OnSoftKeyboardListener listener) {
this.onSoftKeyboardListener = listener;
}
// Simplest possible listener :)
public interface OnSoftKeyboardListener {
public void onShown();
public void onHidden();
}
}
That's about it. Of course you need to use your layout (MyLayout) in your code/xml for it to work. And example from activity:
((MyLayout)findViewById(R.id.layout)).setOnSoftKeyboardListener(newOnSoftKeyboardListener() {
@Override
public void onShown() {
// Do something here
}
@Override
public void onHidden() {
// Do something here
}
});
24、如果让View获取焦点
Android新启动Activity,dialog或者其他窗体中中包含EditText, 新启动的activity的焦点默认在EditText上,这是android系统会弹出软键盘,挤压activity本来的界面,影响美观。因此最好在新窗体创建时,最好在onCreate()方法中将焦点放在另一个view上. view使用requestFocus()焦点,但是如果让button或者textView之类控件直接使用requestFocus()方法,则无法获取焦点,焦点会依然在editText上。
只能在使用View的requestFocus()方法之前调用下面2个方法,view才可获取焦点:
view.setFocusable(true);
view.setFocusableInTouchMode(true);
然后调用 requestFocus()即可获取焦点。
25、android:descendantFocusability用法简析
开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点。原因多半是由于在你自己定义的Item中存在诸如ImageButton,Button,CheckBox等子控件(也可以说是Button或者Checkable的子类控件),此时这些子控件会将焦点获取到,所以常常当点击item时变化的是子控件,item本身的点击没有响应。这时候就可以使用descendantFocusability来解决啦,API描述如下:
android:descendantFocusability
Defines the relationship between the ViewGroup and its descendants when looking for a View to take focus.
Must be one of the following constant values.
该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系。
属性的值有三种:
beforeDescendants:viewgroup会优先其子类控件而获取到焦点
afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点
blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点
通常我们用到的是第三种,即在Item布局的根布局加上android:descendantFocusability=”blocksDescendants”的属性就好了,至此listview点击的灵异事件告一段落
26、xxx is not translated in yyy, zzz 的解决方法
在Android SDK Tool r19之后, Export的时候遇到xxx is not translated in yyy, zzz的问题。例如说"auto_exit" is not translated in zh, zh_CN.
这是因为Android SDK Tool 將 ANDROID_LINT_COMPLETE_REGIONS 改为了需要检查。
临时解决方法:
Eclipse > Preference > Android > Lint Error Checking的Correctness: Messages > MissingTranslate
将 Severity 从 Fetal 改为 Warming
27、关于ActionBar的解决方式
http://blog.csdn.net/fireofstar/article/details/7378824操作步骤:
①先定义menu
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:showAsAction="never"
android:title="@string/action_settings"/>
<item
android:id="@+id/action_add"
android:icon="@drawable/ic_action_refresh"
android:showAsAction="always"
android:title="action_add"/>
<item
android:id="@+id/action_save"
android:icon="@drawable/ic_action_search"
android:showAsAction="ifRoom|withText"
android:title="action_save"/>
<item
android:id="@+id/action_delete"
android:icon="@drawable/ic_action_share_selector"
android:showAsAction="ifRoom|withText"
android:title="action_delete"/>
</menu>
②在Activity中加载,并且添加监听
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_add:
Toast.makeText(this, "action_add", 0).show();
break;
case R.id.action_save:
Toast.makeText(this, "action_save", 0).show();
break;
case R.id.action_delete:
Toast.makeText(this, "action_delete", 0).show();
break;
}
return super.onOptionsItemSelected(item);
}
③修改ActionBar的样式(在values-v14中创建actionbar_style.xml)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- the theme applied to the application or activity -->
<style name="CustomActivityTheme" parent="@android:style/Theme.Holo">
<item name="android:actionBarStyle">@style/MyActionBar</item>
<!-- other activity and action bar styles here -->
</style>
<!-- style for the action bar backgrounds -->
<style name="MyActionBar" parent="@android:style/Widget.Holo.ActionBar">
<item name="android:background">@drawable/daohang</item>
<item name="android:backgroundStacked">@drawable/click_item_1</item>
<item name="android:backgroundSplit">@drawable/click_item_3</item>
</style>
</resources>
④在清单中Activity或者application节点引用样式:
<activity android:theme="@style/CustomActivityTheme"
版主很牛逼http://blog.csdn.net/FireOfStar/article/list/3
28、Java中正则表达式
字符串中的正则表达式特殊符号 2006-06-01 12:25:33问题:
String s1="111+222+333";
System.out.println(s1.split("+").length);
//输出时提示错误:
java.util.regex.PatternSyntaxException: Dangling meta character ''+'' near index
问题出现在加号附近,查询相关的资料显示,+、*、|、等符号在正则表达示中有相应的不同意义。
正则表达式的基本用法 zt
1、“.”为通配符,表示任何一个字符,例如:“a.c”可以匹配“anc”、“abc”、“acc”;
2、“[]”,在[]内可以指定要求匹配的字符,例如:“a[nbc]c”可以匹配“anc”、“abc”、“acc;
但不可以匹配“ancc”,a到z可以写成[a-z],0到9可以写成[0-9];
3、数量限定符号,表示匹配次数(或者叫做长度)的符号:
包括:“*”??0次或者多次
“+”??1次或者多次
“?”??0次或者1次
“{n}”??匹配n次,n为整数
“{n,m}”??匹配从n到m之间的某个数的次数;n和m都是整数;
“{n,}”??匹配n到无穷次之间任意次数;
“{,m}”??匹配0到m之间任意次数;
他们放到匹配格式的后面:
例如:
电话号码:024-84820482,02484820482(假设前面3或者4位,后面7或者8位,并且中间的减号可有可无)
都是符合规定的,那么可以用如下格式来匹配:[0-9]{3,4} -? [0-9]{7,8};
注意:“”为转义字符,因为“-”在正则表达式用有代表一个范围的意义,例如:前面所说的[0-9],
所以它需要转义字符“”进行转义才可使用;
4、“^”为否符号,表示不想匹配的符号,例如:[^z][a-z]+可以匹配所有除“z”开头的以外的所有字
符串(长度大于2,因为“+”表示大于等于1的次数,从第二位开始都是小写英文字符);
如果^放到[]的外边则表示以[]开头的字符串;^[az][a-z]+表示a或者z开头的长度大于等于2的英文字符串;
5、“|”或运算符,例如:a[n|bc|cb]c可以匹配“abcc”,“anc”,“acbc”;
6、“$”以它前面的字符结尾的;例如:ab+$就可以被“abb”,“ab”匹配;
7、一些简单表示方法:
d表示[0-9];D表示[^0-9];w表示[A-Z0-9];W表示[^A-Z0-9];s表示[
f],就是空格字符包括tab,空格等等;S表示[^
f],就是非空格字符;
明白了这些以后,我们再返回头看看它们如何被运用呢?一般来讲只需要加[]、或是\即可。
举例来讲:
String s1="111+222+333";
System.out.println(s1.split("[+]").length);
或是
String s1="111+222+333";
System.out.println(s1.split("\\+").length);
29、Android中获取多媒体音量
通过程序获取android系统手机的铃声和音量。同样,设置铃声和音量的方法也很简单!设置音量的方法也很简单,AudioManager提供了方法:
publicvoidsetStreamVolume(intstreamType,intindex,intflags)其中streamType有内置的常量,去文档里面就可以看到。
JAVA代码:
AudioManager mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
//通话音量
int max = mAudioManager.getStreamMaxVolume( AudioManager.STREAM_VOICE_CALL );
int current = mAudioManager.getStreamVolume( AudioManager.STREAM_VOICE_CALL );
Log.d(“VIOCE_CALL”, “max : ” + max + ” current : ” + current);
//系统音量
max = mAudioManager.getStreamMaxVolume( AudioManager.STREAM_SYSTEM );
current = mAudioManager.getStreamVolume( AudioManager.STREAM_SYSTEM );
Log.d(“SYSTEM”, “max : ” + max + ” current : ” + current);
//铃声音量
max = mAudioManager.getStreamMaxVolume( AudioManager.STREAM_RING );
current = mAudioManager.getStreamVolume( AudioManager.STREAM_RING );
Log.d(“RING”, “max : ” + max + ” current : ” + current);
//音乐音量
max = mAudioManager.getStreamMaxVolume( AudioManager.STREAM_MUSIC );
current = mAudioManager.getStreamVolume( AudioManager.STREAM_MUSIC );
Log.d(“MUSIC”, “max : ” + max + ” current : ” + current);
//提示声音音量
max = mAudioManager.getStreamMaxVolume( AudioManager.STREAM_ALARM );
current = mAudioManager.getStreamVolume( AudioManager.STREAM_ALARM );
Log.d(“ALARM”, “max : ” + max + ” current : ” + current);
ps:
游戏过程中只允许调整多媒体音量,而不允许调整通话音量。
setVolumeControlStream(AudioManager.STREAM_MUSIC);
长时间不动,不允许黑屏,View.setKeepScreenOn(true);
估计manifest文件中需要注册权限吧
30、Android中通过音量键调节音频文件播放的声音
在Android游戏开发中,有两种音量,一种是软音量,软音量可以是通过设置MediaPlayer和SoundPool的音量来实现游戏的声音增减,常见的游戏引擎,如cocos2d-x都有相应的声音引擎来封装软音量方便开发。但是游戏引擎却没提供硬件音量的设置,这需要我们自己来监听手机上的上下两个音量键,来实现对“媒体音量的”调节。
重写Activity中的onKeyDown方法。
private AudioManager audio = (AudioManager) getSystemService(Service.AUDIO_SERVICE);//声音管理类
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP://增大音量
audio.adjustStreamVolume(
AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_RAISE,
AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_SHOW_UI);
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN://减小音量
audio.adjustStreamVolume(
AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_LOWER,
AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_SHOW_UI);
return true;
}
return super.onKeyDown(keyCode, event);
}
31、项目文件上面总是显示有错 gen already exists but is not a source folder
gen already exists but is not a source folder
遇到android项目导入出现后重复空包等错误,往往是导入的java编译级别有关,点击项目properties->
java Compiler ->修改Compiler compliance level 一般是1.6。
修改完成clean项目之后,往往还会遇到:
gen already exists but is not a source folder. Convert to a source folder or rename it的错误遇到这个问题的解决方法:
1. 右键点击工程,选择 "Properties"
2. 选择左边的 "Java Build Path"
3. 打开 "Source" 标签面板
4. 点击 "Add Folder..."
5. 勾选 "gen" 文件夹,点击OK,点击YES,再点击OK
6. 最后右键点击工程,选择 "Andriod Tools" 里面的 "Fix Project Properties"
出现这个问题的原因是classpath文件出错,这个文件存在于项目根目录下,是eclipse自动生成的,它定义了你这个项目在编译时所使用的$CLASSPATH,一般不需要手动配置。如果出错,也可手动修改:
Xml代码 复制代码 收藏代码
1.<?xml version="1.0" encoding="UTF-8"?>
2.<classpath>
3. <classpathentry kind="src" path="src"/>
4. <classpathentry kind="src" path="gen"/>
5. <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
6. <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
7. <classpathentry kind="lib" path="libs/ksoap2-android-assembly-2.5.8-jar-with-dependencies.jar"/>
8. <classpathentry kind="output" path="bin/classes"/>
9.</classpath>
从数据上我们容易看出,上面描述了工程的依赖文件:
源文件的具体位置(kind="src")
运行的系统环境(kind="con")
工程的library的具体位置信息(kind="lib")
项目的输出目录(kind="output")
32、关于WebViewClient方法的解释
1、public boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);
return true;
}
在点击请求的是链接是才会调用,重写此方法返回true表明点击网页里面的链接还是在当前的webview里跳转,不跳到浏览器那边。
2、public void onReceivedSslError(WebView view, SslErrorHandler handler, android.net.http.SslError error) {
handler.proceed();
}
重写此方法可以让webview处理https请求。
3、public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
return super.shouldOverrideKeyEvent(view, event);
}
}
重写此方法才能够处理在浏览器中的按键事件。
4、 public void onLoadResource(WebView view, String url) {
// TODO Auto-generated method stub
if (DEBUG) {
Log.d(TAG, " onLoadResource ");
}
super.onLoadResource(view, url);
}
在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。
5、 public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
if (DEBUG) {
Log.d(TAG, " onPageStarted ");
}
if (url.endsWith(".apk")) {
download(url);//下载处理
}
super.onPageStarted(view, url, favicon);
}
在页面加载开始时调用。
6、public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
if (DEBUG) {
Log.d(TAG, " onPageFinished ");
}
super.onPageFinished(view, url);
}
在页面加载结束时调用。
33、WebviewClient与WebChromeClient的区别
ANDROID应用开发的时候可能会用到WEBVIEW这个组件,使用过程中可能会接触到WEBVIEWCLIENT与WEBCHROMECLIENT,那么这两个类到底有什么不同呢?WebViewClient主要帮助WebView处理各种通知、请求事件的,比如:
onLoadResource
onPageStart
onPageFinish
onReceiveError
onReceivedHttpAuthRequest
WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等比如
onCloseWindow(关闭WebView)
onCreateWindow()
onJsAlert (WebView上alert无效,需要定制WebChromeClient处理弹出)
onJsPrompt
onJsConfirm
onProgressChanged
onReceivedIcon
onReceivedTitle
看上去他们有很多不同,实际使用的话,如果你的WebView只是用来处理一些html的页面内容,只用WebViewClient就行了,如果需要更丰富的处理效果,比如JS、进度条等,就要用到WebChromeClient。
更多的时候,你可以这样
WebView webView;
webView= (WebView) findViewById(R.id.webview);
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient());
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl(url);
这样你的WebView理论上就能有大部分需要实现的特色了
当然,有些更精彩的内容还是需要你自己添加的
34、文件上传的功能:
Android 上传大文件androidexceptionstringnullcommand测试
最近工作需要实现使用 Android 手机上传图片的功能, 参考了网络上的很多资料, 不过网络上的代码都仅仅适合上传较小的文件, 当上传较大文件时(我在自己的测试机器上发现是 2M 左右), 就会因为内存不足发生异常。异常一般发生在两个地方, 1. 将需要上传的文件读取到内存缓存时, 2. 调用 HttpUrlConnection 的 OutputStream 发送数据时。 为了解决这两个问题, 我使用了将上传数据写入临时文件, 然后调用 HttpPost 类来发送数据的办法, 代码如下
private String post(String command, Map<String, String> params, String format, String name, String type, Bitmap content) throws Exception
{
String BOUNDARY = "-------1A2B3C4D5E6F";
String MULTIPART_FORM_DATA = "multipart/form-data";
OutputStream outStream = null;
File tmpFile = iHompyFile.createRandomFile();
if (tmpFile == null)
{
outStream = new ByteArrayOutputStream();
}
else
{
outStream = new FileOutputStream(tmpFile);
}
/**
* 填写数据
*/
try
{
if (params != null)
{
for(Map.Entry<String, String> entry : params.entrySet())
{
outStream.write(("--" + BOUNDARY + "/r/n").getBytes());
outStream.write(("Content-Disposition: form-data; name=/"" + entry.getKey() + "/"/r/n/r/n").getBytes());
outStream.write(entry.getValue().getBytes());
outStream.write(("/r/n").getBytes());
}
}
outStream.write(("--" + BOUNDARY + "/r/n").getBytes());
outStream.write(("Content-Disposition: form-data; name=/"" + format + "/"; filename=/"" + name + "/"/r/n").getBytes());
outStream.write(("Content-Type: " + type + "/r/n/r/n").getBytes());
content.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.write(("/r/n--" + BOUNDARY + "--/r/n").getBytes());
}
catch(Exception e)
{
throw new Exception("向数据流写入数据失败, 可能是内存空间不足!" + e.getMessage());
}
HttpPost httpRequest = new HttpPost(myServer + command);
if (tmpFile != null)
{
outStream.flush();
outStream.close();
FileEntity entity = new FileEntity(tmpFile, MULTIPART_FORM_DATA + "; boundary=" + BOUNDARY);
entity.setContentEncoding("UTF-8");
httpRequest.setEntity(entity);
}
else
{
ByteArrayEntity entity = new ByteArrayEntity(((ByteArrayOutputStream)outStream).toByteArray());
entity.setContentType(MULTIPART_FORM_DATA + "; boundary=" + BOUNDARY);
entity.setContentEncoding("UTF-8");
httpRequest.setEntity(entity);
}
HttpResponse httpResponse = myClient.execute(httpRequest);
int httpCode = httpResponse.getStatusLine().getStatusCode();
if (tmpFile != null)
{
tmpFile.delete();
}
if (httpCode != 200)
{
throw new Exception("Error response: " + httpResponse.getStatusLine().toString());
}
return EntityUtils.toString(httpResponse.getEntity());
}
35、如果给应用添加评分的功能
http://mobile.51cto.com/market-332808.htm36、猴子测试
adb shell monkey -v -p com.lianyou.lottery 50000猴子测试详细解释
http://blog.chinaunix.net/uid-20546441-id-355035.html
37、关于LayoutInflate.inflate第三个参数的作用
http://www.189works.com/article-43331-1.html获取LayoutInflate的方法:
LayoutInflater inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.main, null);
LayoutInflater inflater = LayoutInflater.from(context); (该方法实质就是第一种方法,可参考源代码)
View layout = inflater.inflate(R.layout.main, null);
LayoutInflater inflater = getLayoutInflater();(在Activity中可以使用,实际上是View子类下window的一个函数)
View layout = inflater.inflate(R.layout.main, null);
inflate(int resource, ViewGroup root, boolean attachToRoot) 中,前连个参数都好理解,我比较费解的是第3个参数。
resource:资源文件
root:根目录
attachRoot:如果根目录存在,并且attachToRoot设置为true,就会将加载的resource资源View添加到root下面
38、Java中的线程池与任务队列
http://blog.csdn.net/xcysuccess3/article/details/7551720package test.main;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 测试多线程管理下载任务
*/
public class TestDownload {
public static void main(String[] args) {
// 1.new一个线程管理队列
DownloadTaskManager.getInstance();
// 2.new一个线程池,并启动
DownloadTaskManagerThread downloadTaskManagerThread = new DownloadTaskManagerThread();
new Thread(downloadTaskManagerThread).start();
// 3.请求下载
String[] items = new String[] { "张菲1", "张菲2", "张菲3", "张菲4", "张菲5",
"张菲6", "张菲7", "张菲1", "张菲2" };
for (int i = 0; i < items.length; i++) {
DownloadTaskManager downloadTaskMananger = DownloadTaskManager
.getInstance();
downloadTaskMananger.addDownloadTask(new DownloadTask(items[i]));
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class DownloadTask implements Runnable {
public String name;
public DownloadTask(String name) {
this.name = name;
}
@Override
public void run() {
// String name=Thread.currentThread().getName();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + " executed OK!");
}
public String getFileId() {
return name;
}
}
/**
* 其中downloadTasks表示的是线程队列,taskIdSet是任务队列,作用就是用来管理线程队列,此程序用的是去重操作。已经下载过的文件,
* 不会再次下载。
*/
class DownloadTaskManager {
private static final String TAG = "DownloadTaskManager";
// UI请求队列
private LinkedList<DownloadTask> downloadTasks;
// 任务不能重复
private Set<String> taskIdSet;
private static DownloadTaskManager downloadTaskMananger;
private DownloadTaskManager() {
downloadTasks = new LinkedList<DownloadTask>();
taskIdSet = new HashSet<String>();
}
public static synchronized DownloadTaskManager getInstance() {
if (downloadTaskMananger == null) {
downloadTaskMananger = new DownloadTaskManager();
}
return downloadTaskMananger;
}
// 1.先执行
public void addDownloadTask(DownloadTask downloadTask) {
synchronized (downloadTasks) {
if (!isTaskRepeat(downloadTask.getFileId())) {
// 增加下载任务
downloadTasks.addLast(downloadTask);
}
}
}
public boolean isTaskRepeat(String fileId) {
synchronized (taskIdSet) {
if (taskIdSet.contains(fileId)) {
return true;
} else {
System.out.println("下载管理器增加下载任务:" + fileId);
taskIdSet.add(fileId);
return false;
}
}
}
public DownloadTask getDownloadTask() {
synchronized (downloadTasks) {
if (downloadTasks.size() > 0) {
System.out.println("下载管理器增加下载任务:" + "取出任务");
DownloadTask downloadTask = downloadTasks.removeFirst();
return downloadTask;
}
}
return null;
}
}
class DownloadTaskManagerThread implements Runnable {
private DownloadTaskManager downloadTaskManager;
// 创建一个可重用固定线程数的线程池
private ExecutorService pool;
// 线程池大小
private final int POOL_SIZE = 5;
// 轮询时间
private final int SLEEP_TIME = 1000;
// 是否停止
private boolean isStop = false;
public DownloadTaskManagerThread() {
downloadTaskManager = DownloadTaskManager.getInstance();
pool = Executors.newFixedThreadPool(POOL_SIZE);
}
@Override
public void run() {
while (!isStop) {
DownloadTask downloadTask = downloadTaskManager.getDownloadTask();
if (downloadTask != null) {
pool.execute(downloadTask);
} else { // 如果当前未有downloadTask在任务队列中
try {
// 查询任务完成失败的,重新加载任务队列
// 轮询,
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if (isStop) {
pool.shutdown();
}
}
/**
* @param isStop
* the isStop to set
*/
public void setStop(boolean isStop) {
this.isStop = isStop;
}
}
39、android中软件的评分功能
Android 调用已安装市场,进行软件评分的功能实现http://blog.csdn.net/wangfayinn/article/details/10351655
调用手机中已经安装好的软件,进行评分:比如360手机助手、google play、豌豆荚
Uri uri = Uri.parse("market://details?id="+getPackageName());
Intent intent = new Intent(Intent.ACTION_VIEW,uri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
40、Android Debug模式下的签名
Android应用程序签名http://blog.sina.com.cn/s/blog_69a4fbd70100rrio.html
Android build tools 提供了debug签名模式, 帮助简化应用的开发和调试, 而仍然符合Android系统签名.apk的需求. 当使用debug模式来构建app时, SDK 工具调用 Keytool来自动创建一个用于debug的 keystore 和 key. 然后这个debug key被用来自动签名 .apk, 所以不必用自己的key来签名包.
SDK 工具使用预定义的 名称/密码 来创建keystore/key :
Keystore name: "debug.keystore"
Keystore password: "android"
Key alias: "androiddebugkey"
Key password: "android"
CN: "CN=Android Debug,O=Android,C=US"
如有必要, 可以更改 debug keystore/key 的 location/name 或自己提供一个自定义的 debug keystore/key. 然而, 任何自定义的debug keystore/key必须使用和默认debug key(如之前所述)相同的debug keystore/key 名称和密码.
(Eclipse/ADT中, Windows > Preferences > Android > Build)
注意: 当用debug证书签名时, 应用程序不能对外发布.
如何生成APK签名文件的sha1信息---在百度地图中使用
C:\Users\Orion>keytool -list -v -keystore C:\Users\Orion\Desktop\ihouse -storepass 111111
其中ihouse是签名文件
111111是这个签名文件的密码
http://www.cnblogs.com/qianxudetianxia/archive/2011/04/09/2010468.html
41、 Use View.isInEditMode() in your custom views to skip code when shown in Eclipse
今天在做自定义ViewGroup中,出现了一下错误提示Use View.isInEditMode() in your custom views to skip code when shown in Eclipse
具体解决方法:
在eclipse error log中查看错误具体出现在哪一行,然后将
if (isInEditMode()) { return; }加入即可。
这种方法同样适用于 xml布局文件中null错误。
java.lang.NullPointerException
Exception details are logged in Window > Show View > Error Log
42、集成支付宝玩意儿SDK使用微博
http://www.cnblogs.com/qianxudetianxia/archive/2012/04/04/2432406.html43、EditText:一、点击屏幕其它地方让EditText失去焦点;二、关于EditText默认不弹出键盘的问题
1. 点击屏幕其他地方让edittext失去焦点 的实现方法就是:让EditText所在的layout获得焦点。
给layout注册OnTouchListener监听器
直接使用 .requestFocus() 无法获取焦点,焦点依然在EditTtext上
先调用下面这两个方法:
.setFocusable(true);
.setFocusableInTouchMode(true);
再调用 .requestFocus() 就可获取焦点
//必须
relative.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
relative.setFocusable(true);
relative.setFocusableInTouchMode(true);
relative.requestFocus();
return false;
}
});
// 失去焦点触发
eidt.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View arg0, boolean arg1) {
if (remove_btn.hasFocus() == false) {
//失去焦点时做某事
}
}
}
貌似在拥有ListView的界面里面不太好使用
2.关于EditText的焦点问题(默认进入不弹出键盘)
父控件设置下面属性,拦截焦点即可
android:focusable="true"
android:focusableInTouchMode="true"