- 浏览: 1066001 次
- 性别:
- 来自: 南昌
文章分类
- 全部博客 (276)
- 生活 (1)
- 代码之美 (22)
- Media (7)
- Android Widget (3)
- Android Intent (1)
- Android Activity (4)
- UI event handle--UI事件处理机制 (2)
- Java基础知识 (12)
- android Databases (5)
- Android 系统知识 (70)
- 平常遇到的问题与解决方法 (38)
- Android TextView/EditView (2)
- Thinking Java (1)
- android webkit (6)
- JSON (1)
- XML (4)
- HTTP (1)
- Google Weather API (1)
- android 2.3 NFC (10)
- android app (20)
- android framework (7)
- C++ (2)
- android System (5)
- Pthread (1)
- Wifi (8)
- Unix/Linux C (8)
- Android 4.0 (1)
- Mail (1)
- Smack 源码学习 (4)
- iOS (4)
- Android (1)
- git (1)
- Gallery3d (2)
- React-Natice (1)
最新评论
-
dd18349182956:
你是用的smack哪个版本?我用的smack4.1.3和sma ...
关于socket长连接的心跳包 -
xukaiyin:
全英文
getApplicationContext()与this,getBaseContext() -
裂风矢:
...
<category android:name="android.intent.category.DEFAULT" /> 惹的祸 -
xanthodont:
mark一下
XMPP——Smack -
Evilover3:
mark一下,学习了
XMPP——Smack
转自:http://www.cnblogs.com/loulijun/archive/2012/04/10/2437888.html
引起Android内存泄露有很多种原因,下面罗列了一些问题,以后会一一解决
1、构造Adapter时没有使用缓存convertView(衍生出ListView优化问题)
2、查询数据库游标没有关闭
3、Activity中生命周期对象大于Activity生命周期(关于Application Context与Activity Context)
4、Bitmap对象不使用时没有recycle掉(这里还有其他解决方案)
今天说的是第一种:如何使用缓存来优化ListView
因为如果不使用缓存convertView的话,调用getView时每次都会重新创建View,这样之前的View可能还没有销毁,加之不断的新建View势必会造成内存泄露。
使用getView时有3方案:(1)没有使用convertView,(2)使用convertView,(3)使用convertView+静态类ViewHolder
我做了一个测试,代码在下面,创建2000个View,从0拉到最后,计算总共耗,同时显示GC释放内存的大小,三种测试的结果如下:
注:这里先说下 GC_EXTERNAL_ALLOC freed 7K, 18% free 11153K/13511K, external 1632K/1672K, paused 89ms 的意思
在Dalvik中,为一个程序分配的内存要根据机型的不同而不同,一般为32M,而虚拟机会把这些内存分别分配给,JAVA使用的堆内存(heap)和Nativie使用的内存(external)(即虚拟机中通过JNI调用本地Nativie的类中malloc分配的内存,如Bitmap,java.nio.ByteBuffers)。不过两者不同共享,也就是说Native的内存不够用了,而JAVA内存够用时是不能向JAVA申请的,必须向虚拟机申请才行,当虚拟机无法分配的时候就会报OOM的错误
freed 7k:表示GC已经释放了7K的内存
18% free 11153K/13511K:表示JAVA使用的堆内存(对象存在于此),18% free表示当前剩余18%的堆内存(heap memory),11153K表示当前已用的堆内存,13511K表示堆内存总共大小(网上有些文章这部分弄错了,很多转载都是同一个)
external 1632K/1672K:1632K表示已用external memory,总共1672K external memory(注意:这个可能只存在于Android 3.0之前)
paused 89ms:这里其实包括了两部分,一个是在调用GC之前暂停的时间,一个是调用GC后基本完成时暂停的时间
详细可参考:http://stackoverflow.com/questions/4550757/android-logs-gc-external-alloc-gc-for-malloc
(1)没有使用convertView
没有任何处理,不建议这样写。如果数据量少可以,但是如果列表项数据量很大的时候,会每次都重新创建View,设置资源,严重影响性能,所以从一开始就不要用这种方式
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Get a View that displays the data at the specified position in the data set.
//开始计时,性能测试用nanoTime会更精确,因为它是纳秒级的
long startTime = System.nanoTime();
View item = mInflater.inflate(R.layout.list_item, null);
ImageView img = (ImageView)item.findViewById(R.id.img);
TextView title = (TextView)item.findViewById(R.id.title);
TextView info = (TextView)item.findViewById(R.id.info);
img.setImageResource(R.drawable.ic_launcher);
title.setText("loulijun");
info.setText("www.cnblogs.com/loulijun");
//停止计时
long endTime = System.nanoTime();
//耗时
long spendTime = (endTime - startTime);
sumTime += spendTime;
Log.d("GoogleIO", "position at:"+position+"--sumTime:"+String.valueOf(sumTime));
return item;
}
测试结果:
目前VM只为他们分配了5767K+518k的内存,而内存峰值是32M
刚开始时,而且heap memory只申请了5767K,已用内存3353K,注意数据大小的变化:耗时:167633055ns = 0.167633055秒
当拉到1000的时候,堆内存总计已经申请了9607K,已用内存7245K,明显已经比刚开始时要大了 ,耗时:3435241667ns=3.435241667秒
当拉到2000的时候,堆内存总计13511K,已用内存11153K,耗时:6660369835ns = 6.660369835秒
---------------------------我又创建了10000个ListView,测试后直到内存泄露,证明峰值却是是32M,而不使用convertView导致的内存泄露,当内存泄露时手机会提示force close,并将错误写入/data/anr/traces.txt中,你可以adb pull下来查看具体信息
(2)使用convertView后的测试数据(优化后)
通过缓存convertView,convertView可以缓存可视范围内的convertView,当再次向下滑动时又开始更新View,这种利用缓存convertView的方式可以判断如果缓存中不存在View才创建View,如果已经存在可以利用缓存中的View,这样会减少很多View的创建,提升了性能
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Get a View that displays the data at the specified position in the data set.
if(convertView == null)
{
convertView = mInflater.inflate(R.layout.list_item, null);
}
//开始计时,性能测试用nanoTime会更精确,因为它是纳秒级的
long startTime = System.nanoTime();
ImageView img = (ImageView)convertView.findViewById(R.id.img);
TextView title = (TextView)convertView.findViewById(R.id.title);
TextView info = (TextView)convertView.findViewById(R.id.info);
img.setImageResource(R.drawable.ic_launcher);
title.setText("loulijun");
info.setText("www.cnblogs.com/loulijun");
//停止计时
long endTime = System.nanoTime();
//耗时
long spendTime = (endTime - startTime);
sumTime += spendTime;
Log.d("GoogleIO", "position at:"+position+"--sumTime:"+String.valueOf(sumTime));
return convertView;
}
测试数据我还是用2000吧,10000太大了(一万年太久,只争朝夕)
测试结果:
这次一直拉到最后明显比刚才流畅多了,而且GC释放内存的次数也明显少了很多,最后用的时间和当前使用的内存也小很多,优化后的确好多了
当position为1000的时候,附近没怎么调用GC,用时:213653551ns=0.213653551秒,额,差距有点大,上面到达1000时用时达到3.43秒之多。
当position为2000的时候,已用内存只有3068K,堆总共内存6215K,而且external memory是0K,用时:378326396ns = 0.378326396秒,性能差距如此之大,都有点不敢相信。也不知道这种方式对不对,如有不妥的地方,还希望大牛能给出正确回答
(3)使用contentView+静态类ViewHolder类
通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。
当我们判断 convertView == null 的时候,如果为空,就会根据设计好的List的Item布局(XML),来为convertView赋值,并生成一个viewHolder来绑定converView里面的各个View控件(XML布局里面的那些控件)。再用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。(看下面代码中)
如果convertView不为空的时候,就会直接用convertView的getTag(),来获得一个ViewHolder。
静态类ViewHolder
//定义静态类ViewHolder
static class ViewHolder
{
public ImageView img;
public TextView title;
public TextView info;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Get a View that displays the data at the specified position in the data set.
//开始计时,性能测试用nanoTime会更精确,因为它是纳秒级的
long startTime = System.nanoTime();
ViewHolder holder;
if(convertView == null)
{
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.list_item, null);
holder.img = (ImageView)convertView.findViewById(R.id.img);
holder.title = (TextView)convertView.findViewById(R.id.title);
holder.info = (TextView)convertView.findViewById(R.id.info);
convertView.setTag(holder);
}else
{
holder = (ViewHolder)convertView.getTag();
holder.img.setImageResource(R.drawable.ic_launcher);
holder.title.setText("loulijun");
holder.info.setText("www.cnblogs.com/loulijun");
}
//停止计时
long endTime = System.nanoTime();
//耗时
long spendTime = (endTime - startTime);
sumTime += spendTime;
Log.d("GoogleIO", "position at:"+position+"--sumTime:"+String.valueOf(sumTime));
return convertView;
}
到这里,可能会有人问ViewHolder静态类结合缓存convertView与直接使用convertView有什么区别吗,是否重复了
在这里,官方给出了解释
提升Adapter的两种方法
To work efficiently the adapter implemented here uses two techniques:
-It reuses the convertView passed to getView() to avoid inflating View when it is not necessary
(译:重用缓存convertView传递给getView()方法来避免填充不必要的视图)
-It uses the ViewHolder pattern to avoid calling findViewById() when it is not necessary
(译:使用ViewHolder模式来避免没有必要的调用findViewById():因为太多的findViewById也会影响性能)
ViewHolder类的作用
-The ViewHolder pattern consists in storing a data structure in the tag of the view
returned by getView().This data structures contains references to the views we want to bind data to,
thus avoiding calling to findViewById() every time getView() is invoked
(译:ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构,这个数据结构包含了指向我们
要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById())
测试数据:(跟直接使用convertView数据相差不多)
当position为1000时,用时:199188216ns = 0.199188216秒,堆内存的时候也没比没有使用convertView理想的多
当position为2000时,用时:336669887ns = 0.336669887秒,比直接使用convertView的方式稍微好一点点,不过性能相差不多
引起Android内存泄露有很多种原因,下面罗列了一些问题,以后会一一解决
1、构造Adapter时没有使用缓存convertView(衍生出ListView优化问题)
2、查询数据库游标没有关闭
3、Activity中生命周期对象大于Activity生命周期(关于Application Context与Activity Context)
4、Bitmap对象不使用时没有recycle掉(这里还有其他解决方案)
今天说的是第一种:如何使用缓存来优化ListView
因为如果不使用缓存convertView的话,调用getView时每次都会重新创建View,这样之前的View可能还没有销毁,加之不断的新建View势必会造成内存泄露。
使用getView时有3方案:(1)没有使用convertView,(2)使用convertView,(3)使用convertView+静态类ViewHolder
我做了一个测试,代码在下面,创建2000个View,从0拉到最后,计算总共耗,同时显示GC释放内存的大小,三种测试的结果如下:
注:这里先说下 GC_EXTERNAL_ALLOC freed 7K, 18% free 11153K/13511K, external 1632K/1672K, paused 89ms 的意思
在Dalvik中,为一个程序分配的内存要根据机型的不同而不同,一般为32M,而虚拟机会把这些内存分别分配给,JAVA使用的堆内存(heap)和Nativie使用的内存(external)(即虚拟机中通过JNI调用本地Nativie的类中malloc分配的内存,如Bitmap,java.nio.ByteBuffers)。不过两者不同共享,也就是说Native的内存不够用了,而JAVA内存够用时是不能向JAVA申请的,必须向虚拟机申请才行,当虚拟机无法分配的时候就会报OOM的错误
freed 7k:表示GC已经释放了7K的内存
18% free 11153K/13511K:表示JAVA使用的堆内存(对象存在于此),18% free表示当前剩余18%的堆内存(heap memory),11153K表示当前已用的堆内存,13511K表示堆内存总共大小(网上有些文章这部分弄错了,很多转载都是同一个)
external 1632K/1672K:1632K表示已用external memory,总共1672K external memory(注意:这个可能只存在于Android 3.0之前)
paused 89ms:这里其实包括了两部分,一个是在调用GC之前暂停的时间,一个是调用GC后基本完成时暂停的时间
详细可参考:http://stackoverflow.com/questions/4550757/android-logs-gc-external-alloc-gc-for-malloc
(1)没有使用convertView
没有任何处理,不建议这样写。如果数据量少可以,但是如果列表项数据量很大的时候,会每次都重新创建View,设置资源,严重影响性能,所以从一开始就不要用这种方式
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Get a View that displays the data at the specified position in the data set.
//开始计时,性能测试用nanoTime会更精确,因为它是纳秒级的
long startTime = System.nanoTime();
View item = mInflater.inflate(R.layout.list_item, null);
ImageView img = (ImageView)item.findViewById(R.id.img);
TextView title = (TextView)item.findViewById(R.id.title);
TextView info = (TextView)item.findViewById(R.id.info);
img.setImageResource(R.drawable.ic_launcher);
title.setText("loulijun");
info.setText("www.cnblogs.com/loulijun");
//停止计时
long endTime = System.nanoTime();
//耗时
long spendTime = (endTime - startTime);
sumTime += spendTime;
Log.d("GoogleIO", "position at:"+position+"--sumTime:"+String.valueOf(sumTime));
return item;
}
测试结果:
目前VM只为他们分配了5767K+518k的内存,而内存峰值是32M
刚开始时,而且heap memory只申请了5767K,已用内存3353K,注意数据大小的变化:耗时:167633055ns = 0.167633055秒
当拉到1000的时候,堆内存总计已经申请了9607K,已用内存7245K,明显已经比刚开始时要大了 ,耗时:3435241667ns=3.435241667秒
当拉到2000的时候,堆内存总计13511K,已用内存11153K,耗时:6660369835ns = 6.660369835秒
---------------------------我又创建了10000个ListView,测试后直到内存泄露,证明峰值却是是32M,而不使用convertView导致的内存泄露,当内存泄露时手机会提示force close,并将错误写入/data/anr/traces.txt中,你可以adb pull下来查看具体信息
(2)使用convertView后的测试数据(优化后)
通过缓存convertView,convertView可以缓存可视范围内的convertView,当再次向下滑动时又开始更新View,这种利用缓存convertView的方式可以判断如果缓存中不存在View才创建View,如果已经存在可以利用缓存中的View,这样会减少很多View的创建,提升了性能
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Get a View that displays the data at the specified position in the data set.
if(convertView == null)
{
convertView = mInflater.inflate(R.layout.list_item, null);
}
//开始计时,性能测试用nanoTime会更精确,因为它是纳秒级的
long startTime = System.nanoTime();
ImageView img = (ImageView)convertView.findViewById(R.id.img);
TextView title = (TextView)convertView.findViewById(R.id.title);
TextView info = (TextView)convertView.findViewById(R.id.info);
img.setImageResource(R.drawable.ic_launcher);
title.setText("loulijun");
info.setText("www.cnblogs.com/loulijun");
//停止计时
long endTime = System.nanoTime();
//耗时
long spendTime = (endTime - startTime);
sumTime += spendTime;
Log.d("GoogleIO", "position at:"+position+"--sumTime:"+String.valueOf(sumTime));
return convertView;
}
测试数据我还是用2000吧,10000太大了(一万年太久,只争朝夕)
测试结果:
这次一直拉到最后明显比刚才流畅多了,而且GC释放内存的次数也明显少了很多,最后用的时间和当前使用的内存也小很多,优化后的确好多了
当position为1000的时候,附近没怎么调用GC,用时:213653551ns=0.213653551秒,额,差距有点大,上面到达1000时用时达到3.43秒之多。
当position为2000的时候,已用内存只有3068K,堆总共内存6215K,而且external memory是0K,用时:378326396ns = 0.378326396秒,性能差距如此之大,都有点不敢相信。也不知道这种方式对不对,如有不妥的地方,还希望大牛能给出正确回答
(3)使用contentView+静态类ViewHolder类
通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。
当我们判断 convertView == null 的时候,如果为空,就会根据设计好的List的Item布局(XML),来为convertView赋值,并生成一个viewHolder来绑定converView里面的各个View控件(XML布局里面的那些控件)。再用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。(看下面代码中)
如果convertView不为空的时候,就会直接用convertView的getTag(),来获得一个ViewHolder。
静态类ViewHolder
//定义静态类ViewHolder
static class ViewHolder
{
public ImageView img;
public TextView title;
public TextView info;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Get a View that displays the data at the specified position in the data set.
//开始计时,性能测试用nanoTime会更精确,因为它是纳秒级的
long startTime = System.nanoTime();
ViewHolder holder;
if(convertView == null)
{
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.list_item, null);
holder.img = (ImageView)convertView.findViewById(R.id.img);
holder.title = (TextView)convertView.findViewById(R.id.title);
holder.info = (TextView)convertView.findViewById(R.id.info);
convertView.setTag(holder);
}else
{
holder = (ViewHolder)convertView.getTag();
holder.img.setImageResource(R.drawable.ic_launcher);
holder.title.setText("loulijun");
holder.info.setText("www.cnblogs.com/loulijun");
}
//停止计时
long endTime = System.nanoTime();
//耗时
long spendTime = (endTime - startTime);
sumTime += spendTime;
Log.d("GoogleIO", "position at:"+position+"--sumTime:"+String.valueOf(sumTime));
return convertView;
}
到这里,可能会有人问ViewHolder静态类结合缓存convertView与直接使用convertView有什么区别吗,是否重复了
在这里,官方给出了解释
提升Adapter的两种方法
To work efficiently the adapter implemented here uses two techniques:
-It reuses the convertView passed to getView() to avoid inflating View when it is not necessary
(译:重用缓存convertView传递给getView()方法来避免填充不必要的视图)
-It uses the ViewHolder pattern to avoid calling findViewById() when it is not necessary
(译:使用ViewHolder模式来避免没有必要的调用findViewById():因为太多的findViewById也会影响性能)
ViewHolder类的作用
-The ViewHolder pattern consists in storing a data structure in the tag of the view
returned by getView().This data structures contains references to the views we want to bind data to,
thus avoiding calling to findViewById() every time getView() is invoked
(译:ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构,这个数据结构包含了指向我们
要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById())
测试数据:(跟直接使用convertView数据相差不多)
当position为1000时,用时:199188216ns = 0.199188216秒,堆内存的时候也没比没有使用convertView理想的多
当position为2000时,用时:336669887ns = 0.336669887秒,比直接使用convertView的方式稍微好一点点,不过性能相差不多
发表评论
-
打印调用堆栈
2019-11-15 15:48 488平常我们遇到不清楚代码逻辑的,可以通过打印调用堆栈来理清楚,如 ... -
你知道Log.isLoggable
2018-11-23 14:15 965我们可以通过Log.isLoggable来动态开关log的输出 ... -
android:allowUndo
2018-04-25 16:51 788Android 在Android 23增加了UndoManag ... -
mipmap-xxx
2015-12-10 11:35 1108最近在看AOSP,发现mipmaps, 百度 了一下,发现有各 ... -
《Android.Programming.Pushing.the.Limits].Erik.Hellman》记录1
2015-10-29 10:56 580最近在看《Android.Programming.Pushin ... -
System.currentTimeMillis() uptimeMillis elapsedRealtime 区别
2015-10-28 20:02 1319转自http://blog.csdn.net/wutianyi ... -
GPS的开关设置
2015-09-29 18:36 2039//modify by hyxu 2015-9-30 to s ... -
DialogFragment
2015-09-25 13:56 1052public class YesNoDialog extend ... -
ANDROID L——RecyclerView,CardView导入和使用
2015-07-23 09:51 960转自http://blog.csdn.net/a3969019 ... -
IntentService 和ResultReceiver
2015-07-22 20:00 814转自[url] http://javatechig.com/a ... -
Android media媒体库分析之:分类别统计媒体文件大小
2015-07-21 20:07 554转自http://www.linuxidc.com/Linux ... -
java.lang.IllegalArgumentException: Service Intent must be explicit
2015-07-21 20:03 1307转自:http://www.2cto.com/kf/20150 ... -
Context 和Application Context
2015-02-11 15:14 884http://possiblemobile.com/2013/ ... -
ContentProviderOperation.Builder 中withValue和withValueBackReference的区别
2015-02-10 14:01 2203关于ContentProviderOperation.Buil ... -
AndroidManifest.xml的Service元素 android:process设置
2013-05-30 17:02 11491转自:http://galin.blog.sohu ... -
android中打包含有Activity以及资源文件的jar包在工程中调用
2013-05-28 15:00 1323转自:http://www.cnblogs.com/vaiya ... -
Handler+ExecutorService(线程池)+MessageQueue模式+缓存模式
2012-10-31 14:32 1892转自:http://www.eoeandroid.com/th ... -
Animation
2012-10-30 13:41 1138转自:http://hi.baidu.com/wendaoer ... -
Android onTouchEvent和onInterceptTouchEvent
2012-10-24 15:05 1291ViewGroup里的onInterceptTouchEven ... -
Android 内存管理的相关知识
2012-10-15 14:03 1174最近在读柯元旦的《Android 内核剖析》一书的“内存管理” ...
相关推荐
在资源包中的"Android -- CardView 新闻展示推送效果"可能包含了如何将CardView与通知栏结合的示例代码。由于无法直接验证代码,你需要自行下载并运行,根据错误提示进行调试。这部分代码可以作为学习如何在Android...
1.首先在AndroidManifest.xml中添加使用权限: uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" 2.二行代码实现自定义弹窗view View contentView = inflater.inflate(R.layout.layout_...
在Android应用开发中,ListView是展示大量数据列表的常用组件,尤其在评论页面的实现上,它能够有效地滚动和管理视图,节省内存资源。本示例将详细讲解如何在Android中实现一个评论页面,利用ListView展示用户留言。...
在Android开发中,ListView是一种常用的组件,用于展示大量的列表数据。ListView通过复用视图(ViewHolder)机制,高效地管理屏幕上的多个项。然而,为了提高用户体验,有时我们需要添加一些额外的功能,比如“侧滑...
在Android开发中,有时我们需要为一个视图,如ListView或者RecyclerView,添加一个固定在顶部的头部视图(headerview)。这个头部视图通常用来展示广告、导航栏或者其他重要的信息。`ScrollableLayout`是一个用于...
1. 使用 ListView 显示列表数据:ListView 是 Android 中的一种常用的 UI 组件,用于显示列表数据。我们可以使用 ListView 来显示单列或多列数据。 2. 使用 ArrayList 存储数据:ArrayList 是 Java 中的一种集合类,...
EnglishVersion ->_->:https://github.com/jiang111/awesome-android-tips/blob/master/README-en.md 值得收藏的AS插件 ->_->:... 例如下拉刷新时,可以在 contentView 上加一层遮罩。 canvas.drawRect(0, mContentVi
在Android开发中,ListView是一种常用的组件,用于展示大量的列表数据。`ExpandableListView`是它的扩展,支持子项展开和收起功能,但有时我们可能需要在普通的ListView中实现类似的效果,即“展开和收起”功能。这...
在Android应用开发中,ListView是常用的组件之一,用于展示大量数据列表。然而,手动处理ListView的繁琐性常常会让代码变得复杂且难以维护。为了解决这个问题,开发者们引入了各种库,其中AndroidAnnotations(简称...
1. **创建HeadView和ContentView**:你需要分别创建广告栏和菜单栏的布局文件,作为ListView的头视图(HeadView)和内容视图(ContentView)。这两个视图可以通过`LayoutInflater`从XML布局文件中加载。 2. **...
使用 Android 原生属性动画 Api 解决了锁定 LinearLayout 高度的问题 加入 Alpha 属性动画改进切换键盘时候的用户体验 过滤快速点击事件,机智如我 增加 OnContentViewScrollListener,在键盘弹出或隐藏时,...
MDDialog是一款Material Designed风格的Dialog,可以灵活定制其内容以及显示方式,如:可以添加中间的ContentView,可以对ContentView自由的添加代码操作,如添加点击事件等等;对于多个选项风格的dialog,提供了...
popupWindow.setHeight(totalHeight + listView.getDividerHeight() * (dataList.size() - 1)); ``` 通过以上步骤,我们就成功地在PopupWindow中实现了ListView的自适应显示。这个过程涉及了PopupWindow、ListView...
Android-LibFramework 项目说明 项目描述 一个简单的Android项目基础框架,提供基于注解的资源注入和事件绑定,UI管理,UI log打印等功能,达到快速开发的目的 项目结构 文件和路径 功能 src java 源码文件 ...
问题是性能与神坑"Only fullscreen activities can request orientation"。 将上页ContentView绘制到当前页,侧滑时动画推入推出。(也许挺不错?) 类全面屏返回手势。即刻App的效果(下图)。 本库这里选择了方案...
PopupWindow是Android开发中一个非常实用的组件,它允许开发者创建弹出式窗口,通常用于显示临时信息或者作为其他UI元素的辅助界面。在本文中,我们将深入探讨PopupWindow的基本用法、自定义效果和位置设定,以帮助...
在Android开发中,`PopupWindow`是一个非常实用的组件,它可以用来创建弹出式窗口,通常用于实现下拉菜单、提示信息等效果。...这个示例对于理解和应用`PopupWindow`与`ListView`的结合有着重要的参考价值。
Generally, when writing a page, everyone writes the layout through xml, and loads the xml layout into memory through set contentView or LayoutInflater.from(context).inflate method. advantage Good ...
@Intervene(name = "ContentView", warnAgainst = "setContentView") fun Activity.layout(@LayoutRes layoutRes: Int) { this.setContentView(layoutRes) } @Intervene(name = "ToastIntervention", warnAgains
在Android应用开发中,为了提供更好的用户体验,开发者经常需要向用户显示临时性的提示信息,这就是提示框(Tip)的作用。`PopupWindow`是Android SDK提供的一种轻量级弹出窗口,它可以灵活地显示在屏幕上的任何位置。...