如果你的TextView在ListView/GridView中,会发现设置了android:ellipsize=”marquee”后没有效果,这是因为TextView需要在获取焦点时才会滚动,而如果加了android:focusable=”true”,GridView的焦点被TextView抢走,无法响应点击事件。解决方法:自定义一个View继承系统的TextView,覆盖isFocused()方法,直接返回true,这是因为系统会调用isFocused()方法判断TextView是否已经取到焦点,如果没取到,使用默认的ellipsize=”start” 注:item多时,会明显感觉比不滚动要卡很多,不建议使用,改设计吧
Android开发:Android Studio添加第三方so库
Android Studio现在生成的配置文件还不会自动添加so库,需要在build.gradle里手动加几行代码:
android {
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
把jniLibs.srcDirs = [‘libs’] 放到android.sourceSets.main下,原有的不要删
Android开发:生成圆角(圆形)图片
Android support v4包里已经包含了生成圆角(圆形)的方法,太贴心了.
Bitmap src=BitmapFactory.decodeResource(getResources(),R.drawable.temp_avatar);
RoundedBitmapDrawable roundedBitmapDrawable =
RoundedBitmapDrawableFactory.create(getResources(),src);
//设置圆角半径
roundedBitmapDrawable.setCornerRadius(Math.max(src.getWidth(), src.getHeight()) / 2.0f);
imageViewAvatar.setImageDrawable(roundedBitmapDrawable);
当圆角半径为宽高中最大值的一半时,生成的就是圆形图片.
Android开发:强制ActionBar显示menu图标
默认情况下,在有硬件menu键的手机上,不会显示menu图标(右上角三个点),如果功能依赖这个菜单,可能在对某些用户来说就有些隐晦了,他们可能无法找到这些功能。 要强制系统显示menu图标,可以用反射的方法,把ViewConfiguration对象的sHasPermanentMenuKey属性设为false,让系统以为没有硬件菜单键。
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if (menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception e) {
e.printStackTrace();
}
Android开发:Fragment不同操作的生命周期
下面这张Fragment生命周期图大家应该看得很多了:
但最近在写PageManager(管理页面跳转),发现切换页面时,之前的页面走完onDestoryView就直接onDestory了,回来又重新onCreate,如果用hide和show的方式,都不走生命周期,看了ApiDemo代码,发现原因,整理一下. 切换Fragment有两种方式,一种是add新的,并把旧的hide,另一种是replace. 旧的Fragment为Fragment1,新的是Fragment2,忽略非关键生命周期。 使用add方法切换时: 载入Fragment1 Fragment1 onCreate Fragment1 onCreateView Fragment1 onStart Fragment1 onResume 用以下代码切到Fragment2:
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.hide(Fragment1);
ft.add(R.id.simple_fragment, Fragment2);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
Fragment1不走任何生命周期,但会调onHiddenChanged方法 Fragment2 onCreate Fragment2 onCreateView Fragment2 onStart Fragment2 onResume 回到Fragment1,Remove Fragment2:
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.remove(Fragment2);
ft.show(Fragment1);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
Fragment1还是不走任何生命周期,调onHiddenChanged方法 Fragment2 onPause Fragment2 onStop Fragment2 onDestoryView Fragment2 onDestory 用这种方法切换,Fragment在隐藏时并不会走onDestoryView,所以显示时也不会走onCreateView,所有View都一直保存在内存中。 用replace方法: 载入Fragment1生命周期与上面相同: Fragment1 onCreate Fragment1 onCreateView Fragment1 onStart Fragment1 onResume 切到Fragment2:
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.simple_fragment, Fragment2);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
这次的Fragment1走生命周期了 Fragment1 onPause Fragment1 onStop Fragment1 onDestoryView Fragment1 onDestory Fragment2 onCreate Fragment2 onCreateView Fragment2 onStart Fragment2 onResume 真实打印出来可能是Fragment1和Fragment2混在一起的,可以看到,Fragment1走了onDestory,被完全回收了! 再切回到Fragment1
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.simple_fragment, Fragment1);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
Fragment1 onCreate Fragment1 onCreateView Fragment1 onStart Fragment1 onResume Fragment2 onPause Fragment2 onStop Fragment2 onDestoryView Fragment2 onDestory Fragment1因为已经被回收,又走onCreate,Fragment2被回收。 这两种方式显然都不满足我的需求,且与生命周期图不同。因为我需要在用户看见/看不见Fragment时register和unregister BroadcastReceiver之类的东西(onHiddenChanged也能实现,但第一次载入显示,以及销毁时不会走onHiddenChanged方法),也不希望用户回到上一个Fragment就重新创建整个Fragment,因为这样消耗资源。 看了ApiDemo,发现也是用replace方法,但是,我少了一行:
ft.addToBackStack(null);
在replace时加上这行,可以把原来的Fragment放入栈中,走onDestoryView方法,但不会onDestory,返回时,直接onCreateView,不再onCreate. 返回直接调用popBackStack()方法:
getFragmentManager().popBackStack();
JavaWeb开发:Intellij IDEA+JFinal+Tomcat配置
JFinal官方文档只有Eclipse的配置,但已经习惯了Intellij IDEA,再转回到弱智的Eclipse,实在受不了。 环境是Mac. 先装Tomcat,http://tomcat.apache.org/download-80.cgi,下载Core tar.gz包,解压到合适的位置,比如:/Users/xxx/Documents/Applications/apache-tomcat-8.0.12,Tomcat是免安装的,解压即可使用。 Intellij IDEA必须是Ultimate Edition,免费的社区版是不行的,免费30天。 启动Intellij IDEA,创建Empty Project,完成后,创建新的Module,选择Java-Jave EE-Web Application(3.1),如下图:
左侧Project Settings切到Artifacts,按+号创建 Web Application:Exploded->From Modules和Web Application:Archive->For xxx.第一个用于部署到tomcat,第二个用于生成war包。
增加启动配置:
Application Server设为我们刚下载的Tomcat(先点Configure…,把路径加进来),Open Browser的URL输入http://localhost:8080/目录名,切到Deployment选项卡,按+选择Artifact,选择xxx:war exploded,Application context输入/目录名,与前面的URL路径相同,保存。 改一下index.jsp,随便在body里输入点内容,运行看看能不能看到输出,有输出说明已配好。 接下来在WEB-INF目录下创建lib目录,把JFinal的jar以及其他用到的jar放进来,全选这些jar,点右键,Add as library… 大功告成,接下来看JFinal手册开发即可。
Ubuntu安装Squid代理服务器
需求:安装squid代理,账号认证才能使用 安装: sudo apt-get install squid -y 安装apache2-utils生成账号 sudo apt-get install apache2-utils 生成账号: htpasswd -c /etc/squid3/passwd username 输入两次密码 编辑/etc/squid3/squid.conf,加入: auth_param basic program /usr/lib/squid3/basic_ncsa_auth /etc/squid3/passwd acl ncsa_users proxy_auth REQUIRED http_access allow ncsa_users 重启服务 service squid3 restart 默认squid是不允许匿名访问的。
Android 开发:打印主线程方法栈
除了严格模式外,还可以通过打印主线程方法栈的方式找到耗时操作:
new Thread(){
public void run(){
while (true)
{
try {
Map map=Thread.getAllStackTraces();
Set> stackTraceElementEntry=map.entrySet();
for(Map.Entry entry:stackTraceElementEntry)
{
Thread t=entry.getKey();
StackTraceElement[] stackTraceElements=t.getStackTrace();
if(t.getName().equals("main"))
{
String Tag="STACK_TRACE";
for(StackTraceElement stackTraceElement:stackTraceElements)
{
Log.d(Tag,stackTraceElement.getLineNumber()+" "+stackTraceElement.getClassName()+stackTraceElement.getMethodName());
}
}
}
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
Android开发:捕获未捕捉的异常
未捕捉的异常会让应用Crash,如果是在用户处发生异常,我们无法得到日志,不好解决问题,友盟集成了错误日志收集功能,但我们也可以自己捕捉异常: 定义UnCaughtExceptionHandler,用于处理异常:
public class UnCaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
logToSdcard(thread,ex);
}
public static void logToSdcard(Thread thread,Throwable ex) {
String logFilePath = "";
FileWriter fw = null;
PrintWriter pw = null;
try {
logFilePath = Environment.getExternalStorageDirectory().getPath()+"/crash.log";
File logFile = new File(logFilePath);
if (!logFile.exists()) {
logFile.createNewFile();
}
fw = new FileWriter(logFile,true);
pw = new PrintWriter(fw);
pw.println(String.format("%s\t%s\t%s\t", new Date().toLocaleString(), thread.getName(), ex.toString()));
Throwable cause= ex.getCause();
StackTraceElement[] stackTraceElements=cause.getStackTrace();
for (StackTraceElement stackTraceElement:stackTraceElements)
{
pw.println(String.format("%s\t%s\t%s\t", stackTraceElement.getClassName(), stackTraceElement.getLineNumber(), stackTraceElement.getMethodName()));
}
pw.close();
fw.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
if(pw != null){ try { pw.close(); } catch (Exception e) { }}
if(fw != null){ try { fw.close(); } catch (Exception e) { }}
}
}
}
然后在Application中设置默认异常处理器:
Thread.setDefaultUncaughtExceptionHandler(
new UnCaughtExceptionHandler());
Android开发:去除GridView Item按下时效果(Selector)多余padding
如果不设置自己的selector,默认情况下,在按下item时,会使用默认的selector,而这个selector是有border的,导致显示出来四周会多出几像素。解决方法就是设置自己的selector,不要有border。