相册幻灯片实现以及Activity白屏问题解决
程序员文章站
2022-05-26 19:55:57
...
将相册(自己写,非原生相册)从Android4.4移植到Android6.0上,出现了播放幻灯片,第一张为白屏,后续进入正常的情况
相同的代码,不一样的效果。
首先,我先将幻灯片页面粘出来,并添加注释。
涉及的知识点:BitmapUtils、ViewFlipper
BitmapUtils
// 初始化xutils中的加载图片的工具
mBitmapUtils = new BitmapUtils(this);
// 设置默认加载图片
mBitmapUtils.configDefaultLoadingImage(R.drawable.slide_default);
public View addImageById(String path) {
ImageView iv = new ImageView(this);
// 获取图片路径, 使用路径下载图片, 将图片设置给ImageView, 考虑内存溢出问题, 图片本地缓存
mBitmapUtils.display(iv, path);
return iv;
}
ViewFlipper
private void initView() {
//给组件设置动画
mViewFlipper = (ViewFlipper) findViewById(R.id.imageFlipper);
mViewFlipper.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in));
mViewFlipper.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out)); }
//显示下一个组件
mViewFlipper.showNext();
//动态加载
ViewmViewFlipper.addView(addImageById(path));
public class SlideShowActivity extends Activity implements OnGestureListener {
private static final String TAG = "SlideShowActivity";
public static final String CURRENT_POSITION = "currentPosition";
public static final String ACTION_STOP_SLIDESHOW = "com.avatar.album.stop_slideshow";
private static final int DELAYTIME = 3000;
private static final int SHOWTIME = 3000;
private static final int MSG_HIDECONTROLUI = 1;
private static final int MSG_STOP = 2;
private static final int MSG_SHOW = 3;
public static SlideShowActivity instance = null;
private final List<File> mPicList = new ArrayList<File>();
private ImageView mClose;
private ImageView mPause;
private ImageView mResume;
private RelativeLayout mTopBar;
private RelativeLayout mBottomBar;
private boolean mIsControlUI = true;
private ViewFlipper mViewFlipper;
private BitmapUtils mBitmapUtils;
private ContentResolver mResolver;
private int mCurrentPosition;
private int mCount;
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
//点击屏幕UI的变化
case MSG_HIDECONTROLUI:
if (!mIsControlUI) {
mTopBar.setVisibility(View.GONE);
mBottomBar.setVisibility(View.GONE);
mIsControlUI = true;
}
break;
//播放停止
case MSG_STOP:
setSlideShowResult();
finish();
break;
//播放过程
case MSG_SHOW:
if (mCount >= 0) {
mViewFlipper.showNext();
mHandler.sendEmptyMessageDelayed(MSG_SHOW, SHOWTIME);
mCount--;
mCurrentPosition--;
} else {
Intent intent = new Intent();
intent.putExtra(CURRENT_POSITION, -1);
setResult(Activity.RESULT_OK, intent);
finish();
}
break;
default:
break;
}
}
};
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//这个广播为通过相册主页面停止幻灯片的播放
if (intent.getAction().equals(
HomeFragmentActivity.ACTION_STOP_SLIDE)) {
mHandler.sendEmptyMessage(MSG_STOP);
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.slide_show_photo);
mResolver = this.getContentResolver();
mClose = (ImageView) findViewById(R.id.img_back);
mPause = (ImageView) findViewById(R.id.img_pause);
mResume = (ImageView) findViewById(R.id.img_resume);
mTopBar = (RelativeLayout) findViewById(R.id.top_bar);
mBottomBar = (RelativeLayout) findViewById(R.id.bottom_bar);
mClose.setOnClickListener(clickListener);
mPause.setOnClickListener(clickListener);
mResume.setOnClickListener(clickListener);
mTopBar.setVisibility(View.GONE);
mBottomBar.setVisibility(View.GONE);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(HomeFragmentActivity.ACTION_STOP_SLIDE);
registerReceiver(mBroadcastReceiver, intentFilter);
mBitmapUtils = new BitmapUtils(this);
//加载幻灯片的初始话
mBitmapUtils.configDefaultLoadingImage(R.drawable.slide_default);
//添加动画
initView();
//获取展示相片页面当前的照片位置
mCurrentPosition = getIntent().getIntExtra("currentPosition",
mPicList.size() - 1);
Log.i(TAG, "current position : " + mCurrentPosition);
instance = this;
Cursor cursor = null;
try {
cursor = mResolver.query(Media.EXTERNAL_CONTENT_URI, null, null,
null, null);
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
int dataIndex = cursor.getColumnIndex(Media.DATA);
String path = cursor.getString(dataIndex).toString();
Log.i(TAG, "path " + path);
if (path != null) {
String type = path.substring(path.lastIndexOf("/") + 1);
if (type.contains("jpg")) {
File file = new File(path);
mPicList.add(file);
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
}
}
for (int i = mCurrentPosition; i >= 0; i--) {
String path = mPicList.get(i).toString();
mViewFlipper.addView(addImageById(path));
}
for (int i = mPicList.size() - 1; i > mCurrentPosition; i--) {
String path = mPicList.get(i).toString();
mViewFlipper.addView(addImageById(path));
}
mCount = mPicList.size() - 1;
mHandler.sendEmptyMessageDelayed(MSG_SHOW, SHOWTIME);
mCount--;
mCurrentPosition--;
}
@Override
protected void onResume() {
super.onResume();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
@Override
protected void onPause() {
super.onPause();
mPause.performClick();
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
@Override
protected void onDestroy() {
super.onDestroy();
instance = null;
unregisterReceiver(mBroadcastReceiver);
}
private final OnClickListener clickListener = new OnClickListener() {
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.img_back:
mHandler.sendEmptyMessage(MSG_STOP);
break;
//暂停幻灯片的播放
case R.id.img_pause:
mHandler.removeMessages(MSG_SHOW);
mPause.setVisibility(View.GONE);
mResume.setVisibility(View.VISIBLE);
break;
//继续幻灯片的播放
case R.id.img_resume:
mHandler.sendEmptyMessageDelayed(MSG_SHOW, SHOWTIME);
mPause.setVisibility(View.VISIBLE);
mResume.setVisibility(View.GONE);
break;
}
}
};
private void initView() {
mViewFlipper = (ViewFlipper) findViewById(R.id.imageFlipper);
mViewFlipper.setInAnimation(AnimationUtils.loadAnimation(this,
android.R.anim.fade_in));
mViewFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,
android.R.anim.fade_out));
}
//通过照片的连接链接将其转化为ImageView
public View addImageById(String path) {
ImageView iv = new ImageView(this);
mBitmapUtils.display(iv, path);
return iv;
}
@Override
public boolean onKeyDown(int keyCode, android.view.KeyEvent event) {
if (keyCode == android.view.KeyEvent.KEYCODE_BACK) {
setSlideShowResult();
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onTouchEvent(MotionEvent e) {
final int action = e.getActionMasked();
switch (action) {
case MotionEvent.ACTION_UP:
if (mIsControlUI) {
mTopBar.setVisibility(View.VISIBLE);
mBottomBar.setVisibility(View.VISIBLE);
mIsControlUI = false;
mHandler.removeMessages(MSG_HIDECONTROLUI);
mHandler.sendEmptyMessageDelayed(MSG_HIDECONTROLUI, DELAYTIME);
} else {
mTopBar.setVisibility(View.GONE);
mBottomBar.setVisibility(View.GONE);
mIsControlUI = true;
}
break;
default:
break;
}
return super.onTouchEvent(e);
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
//播放完毕,将结果返回照片展示页面
private void setSlideShowResult() {
Intent intent = new Intent(ACTION_STOP_SLIDESHOW);
Log.i(TAG, "mCount" + mCount + " mPicList" + mPicList.size());
if (-1 <= mCount && mCount < mPicList.size()) {
if (mCurrentPosition >= -1) {
mCurrentPosition++;
} else {
mCurrentPosition += (mPicList.size() + 1);
}
Log.i(TAG, "mHandler.mCount = " + mCount + " mCurrentPosition = "
+ mCurrentPosition);
intent.putExtra(CURRENT_POSITION, mCurrentPosition);
} else {
intent.putExtra(CURRENT_POSITION, -1);
}
sendBroadcast(intent);
}
}
实现幻灯片页面,发现每次重启系统,点开应用播放幻灯片,第一次都会显示白屏,进儿播放正常的幻灯片,而且4.4上是正常的,6.0出现此问题。
我最先想到的是debug检查BitmapUtils获取默认图片以及加载图片转换Bitmap对象是否耗时
long start = System.currentTimeMillis();
mBitmapUtils = new BitmapUtils(this);
mBitmapUtils.configDefaultLoadingImage(R.drawable.slide_default);
long end = System.currentTimeMillis();
Log.i(TAG, (end-start) + "");
截取Log结果(Linux)
2毫秒而已...
此刻我的内心是非常崩溃。
排查哪些地方耗时,包括动画,包括查询数据库,这个过程就不多说了。
最后做出优化:
//这里只粘onCreate和优化部分,将所有可能的耗时操作都在子线程做。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.slide_show_photo);
mResolver = this.getContentResolver();
mClose = (ImageView) findViewById(R.id.img_back);
mPause = (ImageView) findViewById(R.id.img_pause);
mResume = (ImageView) findViewById(R.id.img_resume);
mTopBar = (RelativeLayout) findViewById(R.id.top_bar);
mBottomBar = (RelativeLayout) findViewById(R.id.bottom_bar);
mClose.setOnClickListener(clickListener);
mPause.setOnClickListener(clickListener);
mResume.setOnClickListener(clickListener);
mTopBar.setVisibility(View.GONE);
mBottomBar.setVisibility(View.GONE);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(HomeFragmentActivity.ACTION_STOP_SLIDE);
registerReceiver(mBroadcastReceiver, intentFilter);
long start = System.currentTimeMillis();
initView();
mBitmapUtils = new BitmapUtils(this);
initData();
long end = System.currentTimeMillis();
Log.i(TAG, (end-start) + "ms");
mCurrentPosition = getIntent().getIntExtra("currentPosition",
mPicList.size() - 1);
Log.i(TAG, "current position : " + mCurrentPosition);
instance = this;
}
private void initData() {
new Thread() {
public void run() {
Cursor cursor = null;
try {
cursor = mResolver.query(Media.EXTERNAL_CONTENT_URI, null, null,
null, null);
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
int dataIndex = cursor.getColumnIndex(Media.DATA);
String path = cursor.getString(dataIndex).toString();
Log.i(TAG, "path " + path);
if (path != null) {
String type = path.substring(path.lastIndexOf("/") + 1);
if (type.contains("jpg")) {
File file = new File(path);
mPicList.add(file);
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
}
}
runOnUiThread(new Runnable() {
public void run() {
for (int i = mCurrentPosition; i >= 0; i--) {
String path = mPicList.get(i).toString();
mViewFlipper.addView(addImageById(path));
}
for (int i = mPicList.size() - 1; i > mCurrentPosition; i--) {
String path = mPicList.get(i).toString();
mViewFlipper.addView(addImageById(path));
}
}
});
mCount = mPicList.size() - 1;
mHandler.sendEmptyMessageDelayed(MSG_SHOW, SHOWTIME);
mCount--;
mCurrentPosition--;
};
}.start();
}
看来并不是耗时的问题
排除耗时,还有的可能就是6.0有很多新特性,每次开机加载都比4.4要多用时间和资源,然后咨询了同组的92年已绝顶的大神,给出以下方案。。
修改Activity主题,将其设置为透明色:
<style name="ActivityTheme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsTranslucent">true</item>
</style>
给Activity添加主题:
<activity
android:name="com.avatarmind.album.robot.SlideShowActivity"
android:launchMode="singleInstance"
android:screenOrientation="landscape"
android:theme="@style/ActivityTheme" >
</activity>
白屏变为透明..
用户每次点击播放幻灯片,不会白屏,只是会短暂的透明,也用不了多少毫秒。
缺点:
这种通过主题来给windows设置透明,幻灯片添加的属性动画消失。
那么不让属性动画消失还有什么方法呢?
给Activity添加一张透明的图片:
<style name="ActivityTheme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@drawable/select_nothing</item>
</style>
缺点:
这张透明的图片内存无法回收。
所以,推荐大家使用第一种。 Fighting!
上一篇: C++ 如何从string中删除一个字符
下一篇: JS统计每个字符出现的次数