ListView
notifyDataSetChanged()
当listview所在界面的数据改变了,通知listview的适配器更新界面数据
调用listViewAdapter.notifyDataSetChanged();//通知adapter再次调用getView()刷新界面
getView会被重复调用
在ListView的布局文件中加上 android:layout_height="fill_parent" 或 android:layout_height="0dip"(指定高度),如果不指定layout_height,则getView会被重复调用(10次以上,可能是3、4十次),显示结果可能是0、1、0、0、0、2、...,即使list页面的显示很有可能还是正确的,但调用多次会影响体验和性能,所以要特别注意!
让listview完全透明
android:background="@null"
android:cacheColorHint="@android:color/transparent"
android:divider="@android:color/transparent"
android:listSelector="@android:color/transparent"
divider属性
该属性作用是每一项之间需要设置一个图片做为间隔,默认是横线,android:divider="@drawable/list_driver" 其中 @drawable/list_driver 是一个图片资源,如果不想显示分割线则只要设置为android:divider="@drawable/@null" 就可以了
listview的item得不到焦点
当listview的item包含了Button或者Checkable的子类控件时,点击item不会变色(默认橙黄色),是因为item的焦点被Button或者Checkable的子类控件先获得了,导致item得不到焦点,因此需要在item的xml文件中加入属性android:descendantFocusability="blocksDescendants"
背景选择器的使用
1.方法一:在listview中配置android:listSelector="@drawable/xxx
或者在listview的item中添加属性android:background="@drawable/xxx"
2.方法二:Drawable drawable = getResources().getDrawable(R.drawable.xxx);
ListView.setSelector(drawable);但是这样会出现列表有时候为黑的情况,需要加上:android:cacheColorHint="@android:color/transparent"使其透明。
ImageButton
让button图片铺满整个控件android:background="#00000000"//背景透明
android:scaleType="fitXY" //自适应缩放
ContentProvider && ContentResolver
使用ContentProvider(内容提供器)向其它app共享数据,而其它app要获取这共享的数据则通过ContentResolver(内容解析器)
Android SQLite存取图像的简单方法如下:
//Bitmap to byte[]
public byte[] bmpToByteArray(Bitmap bmp){
//Default size is 32 bytes
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
bmp.compress(Bitmap.CompressFormat.JPEG, 100, bos);
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
return bos.toByteArray();
}
//Cursor to bitmap
Bitmap cursorToBmp(Cursor c, int columnIndex) {
byte[] data = c.getBlob(columnIndex);
try {
return BitmapFactory.decodeByteArray(data, 0, data.length);
} catch (Exception e) {
return null;
}
}
图像存储调用:
ContentValues values = new ContentValues();
values.put("img", bmpToByteArray(bmp);
图像读取调用:
Cursor c = db.rawQuery("select * from info", null);
c.moveToLast();
Bitmap bmp = cursorToBmp(c, c.getColumnIndex("img"));
数据库
if(dbFile.exists()){
mySql = SQLiteDatabase.openOrCreateDatabase(dbFile, null); //创建数据库对象
return;
}
try {
dbFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
mySql = SQLiteDatabase.openOrCreateDatabase(dbFile, null);//创建数据库对象
Activity 发广播实现退出
public abstract class EnterActivity extends BaseActivity {
...
// 写一个广播的内部类,当收到动作时,结束activity
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
unregisterReceiver(this); // 这句话必须要写要不会报错,不写虽然能关闭,会报一堆错
((Activity) context).finish();
}
};
@Override
public void onResume() {
super.onResume();
// 在当前的activity中注册广播
IntentFilter filter = new IntentFilter();
filter.addAction(Attribute.PAGENAME);
registerReceiver(this.broadcastReceiver, filter); // 注册
}
/**
* 关闭
*/
public void close() {
Intent intent = new Intent();
intent.setAction(Attribute.PAGENAME); // 说明动作
sendBroadcast(intent);// 该函数用于发送广播
finish();
}
...
}
JSON中getString() 和optString()
The difference is that optString
returns the empty string (""
) if the key you specify doesn't exist.getString
on the other hand throws a JSONException
. Use getString
if it's an error for the data to be missing, or optString
if you're not sure if it will be there.
这个是在stackoverflow上面看到的,mark一下,简单来说就是optString会在得不到你想要的值时候返回空字符串”“,而getString会抛出异常。
scale(缩放)
scale(float sx, float sy, float px, float py)
sx:x轴缩放比例
sy:y轴缩放比例
px:开始缩放的位置x
py:开始缩放的位置y
(ps:缩放比例最大不大于1时,无论开始缩放的位置在哪里,整个缩放过程都是适应屏幕缩放的!)
translate
translate(float f1, float f2)
f1:view的位置x
f2:view的位置y
(ps:默认view的位置为(0,0))
scrollTo
View.scrollTo(int x, int y)
x:相对于视图原来的x位置,偏移x个像素
y:相对于视图原来的y位置,偏移y个像素
(Ps:向左scroll为正,向右为负)
当多个view的属性要设置成一样时,可以在styles.xml中建立
使用方法:
PopupWindow
1: setFocusable(
true
);//获取焦点
2: setBackgroundDrawable(
new
BitmapDrawable());//返回键自动关闭,不需使用onKeyDown()
布局被键盘挤压了?
在Activity的配置中加入:android:windowSoftInputMode="adjustPan"
ScrollView起始位置不是最顶部的解决办法
最近遇到了打开带有ScrollView的页面布局默认起始位置不是最顶部的情况,最后发现问题是因为ScrollView内部嵌套了gridview,只需要设置gridview获取焦点为false即可。
gridview.setFocusable(false);
如果内部嵌套的是listview,也是同样的处理方法。
PS:网上还查到说可以设置myScrollView.smoothScrollTo(0,20);
android PopupWindow + spinner 后,点击spinner报错:Unable to add window
在android上使用PopupWindow + spinner 做地址选择界面,在点击spinner后,会报错:android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRootImpl$W@42617bc8 is not valid; is your activity running?
这个问题找了很久,网上多是说因为content的activity上下文找不到导致,我试了没有解决问题,在一个国外的论坛中看到了解决方法,在spinner的xml中添加一个属性:android:spinnerMode="dialog",这样就不会报错了。
国外网站链接:http://stackoverflow.com/questions/13709741/clicking-spinner-within-popup-window-causes-windowmanagerbadtokenexception
自定义View时,onLayout之后才能调用getChildAt
Android view中的requestLayout和invalidate方法
requestLayout:当view确定自身已经不再适合现有的区域时,该view本身调用这个方法要求parent view重新调用他的onMeasure onLayout来对重新设置自己位置。
特别的当view的layoutparameter发生改变,并且它的值还没能应用到view上,这时候适合调用这个方法。
invalidate:View本身调用迫使view重画。
任何一个控件没有显示出来,大多是需要重写:
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
向下滚动上拉刷新时,com.handmark.pulltorefresh.library.PullToRefreshScrollView中不能是RelativeLayout布局,就算是加了一层Linearlayout套住RelativeLayout也不行,否则addView后会滚到最前!(正常的话,界面是不动的)
在指定位置切换fragment时,RelativeLayout当内容不足时会发现只包含了内容(布局宽度变窄了),就算里面param的宽度都是fill或match也没用,都是失效的;但是Linearlayout正常!
Fragment里面的Viewpaper不显示内容不执行getItem的解决方案
其实这个问题很简单,只需要在new FragmentPagerAdapter的时候传进去的fragmentManager不要使用getFragmentManager,而使用getChildFragmentManager()即可解决此问题。
android中ScrollView中TextView无法铺满全屏解决方案
在ScrollView的xml中加入android:fillViewport="true"属性就OK
让EditText失去焦点避免自动弹出输入法
如果一进去activity,EditText就获取焦点,弹出输入法界面,无疑是很影响美观的。关于让EditText失去焦点,网上比较多的做法是添加一个visibility=gone的Textview.然后让这个textView获取焦点。不知道是我人品不好还是怎么的。我这样做不行,后来采用另外一种做法,就是在其父组件(布局)上添加以下两句代码:
android:focusable="true"
android:focusableInTouchMode="true"
(Ps:1: 在onPause()执行edittext的clearFocus(); 2: 执行隐藏键盘的方法)
判断键盘弹出
root_layout.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
// TODO Auto-generated method stub
if((oldBottom - bottom) > 200 ){
//键盘弹出
mHandler.sendEmptyMessage(1);
}else if((bottom - oldBottom) > 200){
//键盘收起
mHandler.sendEmptyMessage(2);
}
}
});
一开始我用一个Activity_A类被执行2次,1个是用FLAG_ACTIVITY_REORDER_TO_FRONT启动,另一个用正常的途径启动,希望之后用FLAG_ACTIVITY_REORDER_TO_FRONT启动的是第1个Activity_A_1,用正常的途径启动就打开一个新的Activity_A_2;
研究发现:无论activity栈堆中有多少个Activity_A的实例,用FLAG_ACTIVITY_REORDER_TO_FRONT只会返回栈堆中最顶部的Activity_A的实例!
Handle
无论给handle发什么消息,handle都会等到onCreat()执行完后再处理消息,所以,
无论任何时候,当需要在某个控件初始化后要马上调用,就直接给handle发个消息就可以了,因为这个时候控件肯定已经初始化完毕了!
(Ps:fragment中的setUserVisibleHint()的执行比Oncreat()要早,因此不能在onCreat()中调用post来,只能在setUserVisibleHint()中发消息给handle,否则当执行setUserVisibleHint()时会因控件没有初始化报NullPointException)
如果只要在onCreat()中控件初始化结束后就调用,可以用控件.post(Runnable){};
播放变大一下的动画
/**
* 播放变大一下的动画
* @param view
*/
private void addAnimation(View view) {
float[] vaules = new float[] { 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f,
1.1f, 1.2f, 1.3f, 1.25f, 1.2f, 1.15f, 1.1f, 1.0f };
AnimatorSet set = new AnimatorSet();
set.playTogether(ObjectAnimator.ofFloat(view, "scaleX", vaules),
ObjectAnimator.ofFloat(view, "scaleY", vaules));
set.setDuration(150);
set.start();
}
判断服务是否运行
/**
* 用来判断服务是否运行.
* @param context
* @param className 判断的服务名字
* @return true 在运行 false 不在运行
*/
public static boolean isServiceRunning(Context mContext,String className) {
boolean isRunning = false;
ActivityManager activityManager = (ActivityManager)
mContext.getSystemService(Context.ACTIVITY_SERVICE);
List serviceList
= activityManager.getRunningServices(30);
if (!(serviceList.size()>0)) {
return false;
}
for (int i=0; i
设置Activity背景颜色变暗
// 设置背景颜色变暗
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 0.3f;
计算Bitmap的所占的内存空间
今天做图像缓存需要计算Bitmap的所占的内存空间,于是研究了下Bitmap关于内存占用的API
1、getRowBytes:Since API Level 1,用于计算位图每一行所占用的内存字节数。
2、getByteCount:Since API Level 12,用于计算位图所占用的内存字节数。
经实测发现:getByteCount() = getRowBytes() * getHeight(),也就是说位图所占用的内存空间数等于位图的每一行所占用的空间数乘以位图的行数。
ListView使用ViewHolder极简写法(用起来非常简练,将ViewHolder隐于无形)
public static T getAdapterView(View convertView, int id) {
SparseArray viewHolder = (SparseArray) convertView.getTag();
if (viewHolder == null) {
viewHolder = new SparseArray();
convertView.setTag(viewHolder);
}
View childView = viewHolder.get(id);
if (childView == null) {
childView = convertView.findViewById(id);
viewHolder.put(id, childView);
}
return (T) childView;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_feed_item, parent, false);
}
ImageView thumnailView = getAdapterView(convertView, R.id.video_thumbnail);
ImageView avatarView = getAdapterView(convertView, R.id.user_avatar);
ImageView appIconView = getAdapterView(convertView, R.id.app_icon);
设置Activity透明
说明:AppBaseTheme一般是你application指定的android:theme是啥这里就是啥,否则Activity内部的空间风格可能不一致。
用途:用于模拟Dialog效果,比如再Service中没法用Dialog,就可以用Activity来模拟
代码切换全屏
//切换到全屏
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
//切换到非全屏
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
注意:切换到全屏时,底部的虚拟按键仍然是显示的。次方法可多次调用用于切换
用途:播放器界面经常会用到
调用开发者选项中显示触摸位置功能
android.provider.Settings.System.putInt(getContentResolver(), "show_touches", 1);
设置1显示,设置0不显示。
代码设置TextView的样式
使用过自定义Dialog可能马上会想到用如下代码:
new TextView(this,null,R.style.text_style);
但你运行这代码你会发现毫无作用!正确用法:
new TextView(
new ContextThemeWrapper(
this, R.style.text_style))
保存恢复ListView当前位置
private void saveCurrentPosition() {
if (mListView != null) {
int position = mListView.getFirstVisiblePosition();
View v = mListView.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
//保存position和top
}
}
private void restorePosition() {
if (mFolder != null && mListView != null) {
int position = 0;//取出保存的数据
int top = 0;//取出保存的数据
mListView.setSelectionFromTop(position, top);
}
}
检测字符串中只能包含:中文、数字、下划线(_)、横线(-)
public static boolean checkNickname(String sequence) {
final String format = "[^\\u4E00-\\u9FA5\\uF900-\\uFA2D\\w-_]";
Pattern pattern = Pattern.compile(format);
Matcher matcher = pattern.matcher(sequence);
return !matcher.find();
}
检查有没有应用程序来接受处理你发出的intent
public static boolean isIntentAvailable(Context context, String action) {
final PackageManager packageManager = context.getPackageManager();
final Intent intent = new Intent(action);
List list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
使用TransitionDrawable实现渐变效果
private void setImageBitmap(ImageView imageView, Bitmap bitmap) {
// Use TransitionDrawable to fade in.
final TransitionDrawable td = new TransitionDrawable(new Drawable[] { new ColorDrawable(android.R.color.transparent), new BitmapDrawable(mContext.getResources(), bitmap) });
//noinspection deprecation
imageView.setBackgroundDrawable(imageView.getDrawable());
imageView.setImageDrawable(td);
td.startTransition(200);
}
判断是否是平板(官方用法)
public static boolean isTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
计算字宽
public static float GetTextWidth(String text, float Size) {
TextPaint FontPaint = new TextPaint();
FontPaint.setTextSize(Size);
return FontPaint.measureText(text);
}
注意如果设置了textStyle,还需要进一步设置TextPaint。
Android 中如何关闭线程
针对这个问题可以在线程的run方法里,加一个判断标志。
在需要关闭的时候,将flag置为false: isTrue=false;并且将运行的线程对象挂起然后置为null(假设开启的线程对象为mTestThread) :
mTestThread.interrupt();
mTestThread=null;
再次用到的时候进行如下处理即可:
if(mTestThread==null){
mTestThread=new TestThread();
mTestThread.start();
}
如何更新UI才能不出异常呢?SDK告诉我们,有以下4种方式可以从其它线程访问UI线程:
· Activity.runOnUiThread(Runnable)
· View.post(Runnable)
· View.postDelayed(Runnable, long)
· Handler
其中,重点说一下的是View.post(Runnable)方法。在post(Runnable action)方法里,View获得当前线程(即UI线程)的Handler,然后将action对象post到Handler里。在Handler里,它将传递过来的action对象包装成一个Message(Message的callback为action),然后将其投入UI线程的消息循环中。在Handler再次处理该Message时,直接调用runnable的run方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI。
Android中如何在命令行中查看某个文件的内容
第一:采用Eclipse中自带的 File Explorer 工具把该文件导出来[pull a file from the device]。第二:在命令行窗口中使用命令来查看该文件。
我们看到使用 【cat + 文件名.后缀】 的方式即可以查看该文件的内容。
ListView左右滑动删除Item效果
在判断到滑动事件后,加入一下代码,取消子item的点击事件!
//当手指滑动item,取消item的点击事件,不然我们滑动Item也伴随着item点击事件的发生
MotionEvent cancelEvent = MotionEvent.obtain(ev);
cancelEvent.setAction(MotionEvent.ACTION_CANCEL |
(ev.getActionIndex()<< MotionEvent.ACTION_POINTER_INDEX_SHIFT));
onTouchEvent(cancelEvent);
eclipse插件OpenExplorer快速打开文件目录
OpenExplorer插件可以满足这个功能,可以到https://github.com/samsonw/OpenExplorer/downloads下载最新版本,将jar包放到eclipse的plugins目录中,重新启动eclipse后,选中要查看的目录,点击上方横向工具栏中的Open Explorer图标可以实现在window资源管理器中查看目录。
避免APP启动闪白屏
其实就算你onCreate啥都不做,仍然会闪一下白屏,因为初始化解析界面时需要一定时间,解决方法是自定义Theme。
自定义如下
配置文件中配置如下
-
- android:theme="@style/AppSplash"
- android:name=".SplashActivity" >
-
这样一来,点击应用图标之后会马上有响应,出现设置的背景图片,跟QQ、微信效果一样。
android使用百度地图SDK 去掉百度Logo的小技巧
//不显示默认的缩放控件
mMapView.showZoomControls(false);
//不显示默认比例尺控件
mMapView.showScaleControl(false);
// 隐藏logo
View child = mMapView.getChildAt(1);
if (child != null && (child instanceof ImageView || child instanceof ZoomControls)){
child.setVisibility(View.INVISIBLE);
}
下载SDK的代理设置:
服务器:ubuntu.buct.edu.cn
端口:80
界面布局获取不到视图或者高度不准确
可以试试动态addView,99%成功哦!
在使用shape的同时,用代码修改shape的颜色属性
private GradientDrawable getGradientDrawable(int color){
GradientDrawable gd = new GradientDrawable();
gd.setColor(color);
gd.setCornerRadius(15);
gd.setStroke(0, color);
return gd;
}
或者
GradientDrawable myGrad = (GradientDrawable)view.getBackground();
myGrad.setColor(color);
但是如果想设置Gradient的渐变色该咋办呢?
方法是改变GradientDrawable的创建方法:
int colors[] = { 0xff255779 , 0xff3e7492, 0xffa6c0cd };//分别为开始颜色,中间夜色,结束颜色
GradientDrawable gd = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
参考:
http://stackoverflow.com/questions/17667964/how-to-create-shape-with-solid-corner-stroke-in-java-code
http://stackoverflow.com/questions/4177401/gradientdrawable-in-code
百度地图
private GeoCoder mSearch = null; // 搜索模块,也可去掉地图模块独立使用
mSearch = GeoCoder.newInstance();
mSearch.setOnGetGeoCodeResultListener(new MyGetGeoCoderResultListener());// 反Geo搜索,将获取到的详细地址显示到UI中
mSearch.reverseGeoCode(new ReverseGeoCodeOption().location(latLng));// Geo搜索,获取经纬度
mSearch.geocode(new GeoCodeOption().city("").address(result.getAddress()));
软键盘
使用android:imeOptinos可对Android自带的软键盘进行一些界面上的设置:
android:imeOptions="flagNoExtractUi" //使软键盘不全屏显示,只占用一部分屏幕同时,这个属性还能控件软键盘右下角按键的显示内容,默认情况下为回车键
android:imeOptions="actionNone"//输入框右侧不带任何提示
android:imeOptions="actionGo" //右下角按键内容为'开始'
android:imeOptions="actionSearch" //右下角按键为放大镜图片,搜索
android:imeOptions="actionSend" //右下角按键内容为'发送'
android:imeOptions="actionNext"//右下角按键内容为'下一步'
android:imeOptions="actionDone"//右下角按键内容为'完成'
取消EditText获取焦点弹出软键盘
1.
2.android:windowSoftInputMode="stateAlwaysHidden" />
3.
et.setFocusableInTouchMode(false);
et.post(new Runnable() {
@Override
public void run() {
et.setFocusableInTouchMode(true);
}
});
适配2.3
ScrollView里面不能有listview
不能用alpha设置透明度
CompatListView或 ListView
listview加缓存颜色::::android:cacheColorHint="@color/transparent"
numberpassword2.3不可用
BuildConfig.DEBUG
1.如果Build Automatically选中,直接在eclipse点击右键运行项目,DEBUG会一直为ture,因为都是使用调试签名
2.如果Build Automatically选中,使用自己的签名打包,DEBUG依然为true
3.如果Build Automatically未选中,使用自己的签名打包,DEBUG才为false
禁止EditText输入内容
editText.setKeyListener(null);
在Listview的item的高度一样时,计算滑动的距离
public int getScrollY() {
View c = mListView.getChildAt(0);
if (c == null) {
return 0;
}
int firstVisiblePosition = mListView.getFirstVisiblePosition();
int top = c.getTop();
return -top + firstVisiblePosition * c.getHeight() ;
}
Android中监听ScrollView滑动停止和滑动到底部
点击打开链接
FLAG_ACTIVITY_REORDER_TO_FRONT
如果栈中有要打开的activity,直接将改activity提到栈顶,这个时候传Bundle无效
根据密钥获取SHA1
命令:keytool -list -keystore 地址
AndroidStudio导入项目一直卡在Building gradle project info最快速解决方案
原因:实际上是因为你导入的这个项目使用的gradle与你已经拥有的gradle版本不一致,导致需要下载该项目需要的gradle版本,因为被墙了,所以下载不到;
解决方案:
1.随便找一个你能运行的as项目
2.打开gradle-wrapper.properties,文件目录:项目/gradle/wrapper/gradle-wrapper.properties
3.复制distributionUrl这一整行的内容,eg: distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
4.打开你要导入的项目的gradle-wrapper.properties,具体步骤与步骤2相同
5.把步骤3复制的内容,替换你要导入的项目的gradle-wrapper.properties文件的distributionUrl这一行
6.替换build.gradle中的buildToolsVersion,eg:“buildToolsVersion"23.0.1" ;
7.再重启as,导入项目就可以了
将eclipse的项目导出gradle后设置so文件路径
jniLibs.srcDirs = ['libs']
Git添加忽略文件
注意: .gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。
正确的做法是在每个clone下来的仓库中手动设置不要检查特定文件的更改情况。
git update-index --assume-unchanged PATH 在PATH处输入要忽略的文件。
另外 git 还提供了另一种 exclude 的方式来做同样的事情,不同的是 .gitignore 这个文件本身会提交到版本库中去。用来保存的是公共的需要排除的文件。而 .git/info/exclude 这里设置的则是你自己本地需要排除的文件。 他不会影响到其他人。也不会提交到版本库中去。
Android Studio简单设置
http://ask.android-studio.org/?/article/14
App按返回键回到桌面,不关闭Activity
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
moveTaskToBack(false);
return true;
}
return super.onKeyDown(keyCode, event);
}
Android 自动滚动的GridView
GridView两个属性
android:stackFromBottom="true"
android:transcriptMode="alwaysScroll"
列表将一直停顿在下面,当你动态添加数据时,列表将自动往下滚动,保持最下面的Item显示出来
WebView常见问题及解决方案汇总
http://www.cnblogs.com/lee0oo0/p/4026774.html
加载asset文件夹的html文件
mWebView.loadUrl("file:///android_asset/index.html");
Java保留小数点后两位
private DecimalFormat df = new DecimalFormat("#.##");
String占位符
比例%1$d%%,金额¥%2$d元
ps:int用d,string用s;
反编译
第一步
首先我们直接用一个解压apk(开发过android应该知道apk其实就是个压缩文件),解压之后拷贝出里面classes.dex文件待用。
第二步
下载dex2jar工具,最新版下载链接dex2jar下载
解压之后,打开cmd,进入解压目录,运行命令:
d2j-dex2jar.bat classes.dex(上一步解压的) jarpath(反编译dex后的文件目录)
example:
d2j-dex2jar.bat c:\user\qting\classes.dex c:\user\qting\
*反编译之后,会得到一个classes-dex2jar.jar文件,待用。
第三步
下载JD-GUI(反编译jar神器),最新版下载链接JD-GUI下载
解压之后,双击打开,直接把上一步得到的的classes-dex2jar.jar文件直接拖入JD-GUI里面,你就可以查看源码了。
Android调用js
// 无参数调用
webView.loadUrl("javascript:methodName()");
// 传递参数调用
webView.loadUrl("javascript:methodName(" + "´hello world´" + ")");
Fragment
添加fragment入栈时,用add不会走任何生命周期?用replace会走到onDestoryView?记得加上ft.addToBackStack(null);
把EditText的Ime Options属性设置成不同的值,Enter键上可以显示不同的文字或图案。
actionNone : 回车键,按下后光标到下一行
actionGo : Go,
actionSearch : 一个放大镜
actionSend : Send
actionNext : Next
actionDone : Done,隐藏软键盘,即使不是最后一个文本输入框
混淆
如果使用了EventBus之类的库,通过识别固定的方法名字来回调的,就一定不能混淆这个类,或者说这个类的方法名!
Android保存图片到系统图库
http://blog.csdn.net/xu_fu/article/details/39158747
Android横竖屏切换
http://blog.csdn.net/wulianghuan/article/details/8603982
用命令查看apk的版本号等信息
1、首先找到aapt工具,在Android SDK文件夹下的build-tools包里;
2、然后使用aapt dump bading XXX.apk就能看到VersionCode等信息
aapt dump badging C:/Users/kuguan/Desktop/app-release_1.0.9.apk
android studio 忽略文件
app的build.gradle文件,使用fileTree编译libs里面的所有库
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
//compile files('libs/ShareSDK-Core-2.7.4.jar')
}
从Eclipse转Android Studio;
直接在AS点击import project,然后选择eclipse的主项目就可以了,AS会自动找依赖项目的,所以不需要选上依赖项目,之后它会要求你输入一个在AS中展示的项目名,然后将新生成的整个AS项目放入到以这个名字命名的文件夹中,不会覆盖原来的eclipse项目的代码;
ps:AS从eclipse导入项目这个功能,生成新项目时,导入的只是AS认为必须的文件,如果自己定义了的一些文件,AS就不会导入了,所以如果自己有额外的一些文件的话,需要手动复制过去!
这个时候,as的项目已经生成了,可能会报错:(因为AS比eclipse的检查要严格多了!)
1:报点9图错误;
2:依赖库重复了;
等等;
而且还要在app的build.gradle中
defaultConfig{
multiDexEnabled true
}
微信Tinker的使用
在app的build.gradle中修改设置:
tinkerId =
"xxxxxxx"
ignoreWarning = true
使用tinker时,在app的build.gradle中使用了以下代码,导致安装完项目后无法启动!
dependencies{
compile "com.android.support:appcompat-v7:23.1.1"
}
跑完生成的app包会放在app/build/bakApk/目录下;在app的build.gradle文件找到tinkerOldApkPath这一项设置,并将其设置为tinkerOldApkPath = "${bakPath}/<刚才生成的apk文件名>"上面是打基准包的;然后在代码修改后,在Gradle脚本中找到’app:/tinker/tinkerPatchDebug’这条命令(见图4), 双击运行,它将生成debug版的patch(补丁)apk文件.生成的差异包在:app\build\outputs\tinkerPatch\debug\patch_signed_7zip.apk
Gson使用toJson方法时
gson直接new出来的话,使用toJson方法有可能报:
Caused by: java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: java.util.List. Forgot to register a type adapter?
如果使用以下方法创建gson对象,使用toJson方法完全没问题;就算model实现Serializable也不会有影响。
Gson gson = new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
.serializeNulls()
.create();
FLAG_ACTIVITY_NEW_TASK
如果你启动activity使用的flag为FLAG_ACTIVITY_NEW_TASK,而该activity的lauchMode为SINGLE_TASK或SINGLE_INSTANCE的时候,activity如果没打开就打开一个新的,如果已经打开了,只回调onNewIntent方法!
请求权限
ActivityCompat.requestPermissions
Monkey
adb shell monkey -p com.a.b -v 1000
(-p后面加上包名,-v后面加上次数,若adb有多部机器,在adb后加上“-s 机器名”,查询机器名:adb devices)
ScrollView高度全屏
android:fillViewport="true"
NumberPicker中ArrayIndexOutOfBoundsException解决方案
ps: 在设置最大值和最新数组数据前,先将数据设为null
private void initMinuteNumberPicker(int index){
List displayedValues = new ArrayList();
for (int i = index; i < 60; i += 5) {
displayedValues.add(String.format("%02d", i));
}
minuteNumberPicker.setMinValue(0);
minuteNumberPicker.setDisplayedValues(null);
minuteNumberPicker.setMaxValue(displayedValues.size() - 1);
minuteNumberPicker.setValue(0);//设置当前显示第几个
minuteNumberPicker.setDisplayedValues(displayedValues.toArray(new String[0]));
minuteNumberPicker.setWrapSelectorWheel(true);
}
Fragment not attached to Activity
//Return true if the fragment is currently added to its activity.
if(isAdded()){
getResources().getString(R.string.app_name);
}
动态创建控件时
先判断activity是否存在+running,如果不,则不处理!
自动化测试工具:
selenium针对web。app的话可以使用appium, appium的核心就是selenium。
AndroidStudio打包方式:
mac必须获取最高权限:chmod 777 gradlew
打包命令:./gradlew assembleRelease
界面打包:
Signature Versions的选择;
V1 true
V2 false(安装不了,没有任何提示,应该时没有对apk进行签名吧)
V1+V2 true
模拟系统后台杀死app :
有以下几种方法可以实现:(注意:当app在后台时,3种方法都一样效果;但app在前台时,前2种方法出现假死现象,界面无法操作了,重新进入app时,你会发现当前的界面是原来界面的上一个界面,系统已经将顶部的activity移除掉(所以如果当前只有一个activity时,你看到的将会是一个全新的启动app的过程);第3种方法无效)
1:open DDMS(tools->Android->Android Device Monitor)->press Stop;
2:打开Android Monitor,选择进程,点击红圈的X(terminate);
3:在cmd中:adb shell am kill 包名(app必须在后台,否则无效);