我已经适应从AOSP的launcher2WallpaperChooser&放了code; WallpaperChooserDialogFragment是一个独立的图库应用程序,我想它的API级别7工作到16 API
要使它成为API级别和LT工作; 11我加入了Android的支持库(1版)保持兼容包,V4包。
我根据我对从这里的建议将保持兼容包(android.support.v4.app.DialogFragment.java)的变化:DialogFragments与设备API级< 11 。
否则应用程序将一个错误(DialogFragment不能连接到一个容器视图)。
崩溃然而,应用程序拒绝在部署到实际的果冻豆4.1.1设备(的Nexus S)为准备工作,但它完美罚款模拟器。
&测试放大器;适用于:
Android 2.1的模拟器(API 7) Android 2.2的模拟器(API 8) 的Android 2.3.3模拟器(API 10) 的Android 4.0.3模拟器(API 15)是Android 4.1模拟器(API 16)
的Android 2.3.7设备(API 10)
&测试放大器;不工作:
的Android 4.1.1设备(API 16)![AndroidStudiocom.Android.dex.DexException Multipledexfilesdefine 重复引用包](https://p.xsw88.cn/allimgs/daicuo/20230906/2812.png)
在4.1.1设备上运行,它永远不会加载/显示水平视图对他们攻时,图库图片
只显示每张照片选择并旋转设备后,然后再次,选择一个新的图片,再次旋转,并正确显示。
我没有设法找出原因,因此任何帮助是AP preciated那就不是一个真正的设备上正常工作的问题。如果我删除保持兼容包并只针对API级别+11,应用程序的工作真正4.1.1设备上。
这是code的应用程序:
GalleryDemo.java:
包gallery.android.demo;进口android.support.v4.app.DialogFragment;进口android.support.v4.app.Fragment;进口android.support.v4.app.FragmentActivity;进口android.os.Bundle;公共类GalleryDemo扩展FragmentActivity {@覆盖公共无效的onCreate(捆绑冰柱){ super.onCreate(冰柱); 的setContentView(R.layout.wallpaper_chooser_base); 片段fragmentView = getSupportFragmentManager()findFragmentById(R.id.wallpaper_chooser_fragment)。 如果(fragmentView == NULL){ DialogFragment片段= GalleryDemoDialogFragment.newInstance(); fragment.show(getSupportFragmentManager(),对话); }}}
GalleryDemoDialogFragment.java:
包gallery.android.demo;进口android.support.v4.app.DialogFragment;进口android.support.v4.app.FragmentActivity;进口android.annotation.TargetApi;进口android.app.Dialog;进口android.content.DialogInterface;进口android.content.res.Resources;进口android.graphics.Bitmap;进口android.graphics.BitmapFactory;进口android.graphics.Canvas;进口android.graphics.ColorFilter;进口android.graphics.drawable.Drawable;进口android.os.AsyncTask;进口android.os.Build;进口android.os.Bundle;进口android.util.Log;进口android.view.LayoutInflater;进口android.view.View;进口android.view.View.OnClickListener;进口android.view.ViewGroup;进口android.widget.AdapterView;进口android.widget.BaseAdapter;进口android.widget.Gallery;进口android.widget.ImageView;进口android.widget.ListAdapter;进口android.widget.SpinnerAdapter;进口android.widget.Toast;进口的java.util.ArrayList;@燮pressWarnings(德precation)@TargetApi(16)公共类GalleryDemoDialogFragment扩展DialogFragment实现AdapterView.OnItemSelectedListener,AdapterView.OnItemClickListener {私有静态最后弦乐TAG =GalleryDemoDialogFragment;私有静态最后弦乐EMBEDDED_KEY =gallery.android.demo.GalleryDemoDialogFragment.EMBEDDED_KEY;私人布尔mEmbedded;私人位图mBitmap = NULL;私人的ArrayList<整数GT; mThumbs;私人的ArrayList<整数GT; mImages;私人WallpaperLoader mLoader;私人WallpaperDrawable mWallpaperDrawable =新WallpaperDrawable();公共静态的newInstance GalleryDemoDialogFragment(){ GalleryDemoDialogFragment片段=新GalleryDemoDialogFragment(); fragment.setCancelable(真); 返回片段;}@覆盖公共无效的onCreate(捆绑savedInstanceState){ super.onCreate(savedInstanceState); 如果(savedInstanceState = NULL&放大器;!&安培; savedInstanceState.containsKey(EMBEDDED_KEY)){ mEmbedded = savedInstanceState.getBoolean(EMBEDDED_KEY); }其他{ mEmbedded = isInLayout(); }}@覆盖公共无效的onSaveInstanceState(捆绑outState){ outState.putBoolean(EMBEDDED_KEY,mEmbedded);}私人无效cancelLoader(){ 如果(mLoader = NULL&放大器;!&安培;!mLoader.getStatus()= WallpaperLoader.Status.FINISHED){ mLoader.cancel(真); mLoader = NULL; }}@覆盖公共无效onDetach(){ super.onDetach(); cancelLoader();}@覆盖公共无效的onDestroy(){ super.onDestroy(); cancelLoader();}@覆盖公共无效onDismiss(DialogInterface对话){ super.onDismiss(对话); FragmentActivity活性= getActivity(); 如果(活动!= NULL){ activity.finish(); }}@覆盖公共对话框onCreateDialog(捆绑savedInstanceState){ findWallpapers(); 返回null;}@TargetApi(16)@覆盖公共查看onCreateView(LayoutInflater充气器,容器的ViewGroup,捆绑savedInstanceState){ findWallpapers(); 如果(mEmbedded){ 查看查看= inflater.inflate(R.layout.wallpaper_chooser,集装箱,FALSE); 开关(Build.VERSION.SDK_INT){ 案例Build.VERSION_ codeS.ICE_CREAM_SANDWICH: view.setBackgroundDrawable(mWallpaperDrawable); 打破; 案例Build.VERSION_ codeS.JELLY_BEAN: view.setBackground(mWallpaperDrawable); 打破; 默认: view.setBackgroundDrawable(mWallpaperDrawable); 打破; } 最后的画廊画廊=(图库论坛)view.findViewById(R.id.gallery); gallery.setCallbackDuringFling(假); gallery.setOnItemSelectedListener(本); gallery.setAdapter(新ImageAdapter(getActivity())); 查看SET按钮= view.findViewById(R.id.set); setButton.setOnClickListener(新OnClickListener(){ @覆盖 公共无效的onClick(视图v){ INT位置= gallery.getSelectedItemPosition(); 的String [] = wallpaperArray getResources()getStringArray(R.array.wallpapers)。 字符串名称= wallpaperArray [位置] +JPG; Log.i(TAG,位置=+位置); Log.i(TAG,文件名=+姓名); Toast.makeText(getActivity()。getApplicationContext()(Save2SD) n+ 位置=+位置+ n+ 文件名=+名字+ ,Toast.LENGTH_SHORT).show(); } }); 返回视图。 } 返回null;}@覆盖公共无效onItemClick(适配器视图<>母公司,观景,INT位置,长的id){}@覆盖公共无效onItemSelected(适配器视图<>母公司,观景,INT位置,长的id){ 如果(mLoader = NULL&放大器;!&安培;!mLoader.getStatus()= WallpaperLoader.Status.FINISHED){ mLoader.cancel(); } Log.d(TAGonItemSelected()); mLoader =(WallpaperLoader)新WallpaperLoader()执行(位置)。}@覆盖公共无效onNothingSelected(适配器视图<>母公司){}私人无效findWallpapers(){ mThumbs =新的ArrayList<整数GT;(24); mImages =新的ArrayList<整数GT;(24); 最后的资源资源= getResources(); 最后弦乐的packageName = resources.getResourcePackageName(R.array.wallpapers); addWallpapers(资源的packageName,R.array.wallpapers); addWallpapers(资源的packageName,R.array.extra_wallpapers);}私人无效addWallpapers(资源资源,字符串的packageName,诠释名单){ 最终的String [] =额外resources.getStringArray(名单); 对于(字符串额外:演员){ INT解析度= resources.getIdentifier(额外的绘制的packageName); 如果(RES!= 0){ 最终诠释thumbRes = resources.getIdentifier(额外+_small,绘制的packageName); 如果(thumbRes!= 0){ mThumbs.add(thumbRes); mImages.add(RES); } } }}私有类ImageAdapter扩展了BaseAdapter实现ListAdapter,SpinnerAdapter { 私人LayoutInflater mLayoutInflater; ImageAdapter(FragmentActivity活动){ mLayoutInflater = activity.getLayoutInflater(); } 公众诠释的getCount(){ 返回mThumbs.size(); } 公共对象的getItem(INT位置){ 返回的位置; } 众长getItemId(INT位置){ 返回的位置; } 公共查看getView(INT位置,查看convertView,父母的ViewGroup){ 查看视图。 如果(convertView == NULL){ 鉴于= mLayoutInflater.inflate(R.layout.wallpaper_item,父母,假); }其他{ 鉴于= convertView; } ImageView的IV =(ImageView的)view.findViewById(R.id.wallpaper_image); INT thumbRes = mThumbs.get(位置); iv.setImageResource(thumbRes); 可绘制thumbDrawable = iv.getDrawable(); 如果(thumbDrawable!= NULL){ thumbDrawable.setDither(真); }其他{ Log.e(TAG,错误解码缩略图渣油=+ thumbRes +壁纸#+位置); } 返回视图。 }}私有类WallpaperLoader扩展的AsyncTask<整数,太虚,位图> { BitmapFactory.Options mOptions; WallpaperLoader(){ mOptions =新BitmapFactory.Options(); mOptions.inDither = FALSE; mOptions.in preferredConfig = Bitmap.Config.ARGB_8888; } @覆盖 保护位图doInBackground(整数... PARAMS){ 如果(isCancelled())返回NULL; 尝试{ 返回BitmapFactory.de codeResource(getResources(),mImages.get(PARAMS [0]),mOptions); }赶上(OutOfMemoryError异常五){ 返回null; } } @覆盖 保护无效onPostExecute(位图B){ 如果(二== NULL)回报; 如果(isCancelled()及!&放大器;!mOptions.mCancel){ 如果(mBitmap!= NULL){ mBitmap.recycle(); } 视图V = getView(); 如果(V!= NULL){ Log.d(TAGWallpaperLoader.onPostExecute()getView!= NULL); mBitmap = B; mWallpaperDrawable.setBitmap(二); //不会出现与果冻豆(物理)设备(4.1.1)上运行? v.postInvalidate(); }其他{ Log.d(TAGWallpaperLoader.onPostExecute(位图B)getView ==空); mBitmap = NULL; mWallpaperDrawable.setBitmap(NULL); } mLoader = NULL; }其他{ b.recycle(); } } 无效取消(){ mOptions.requestCancelDe code(); super.cancel(真); }}私有静态类WallpaperDrawable扩展可绘制{ 位图mBitmap; INT mIntrinsicWidth; INT mIntrinsicHeight; 无效setBitmap(位图位图){ Log.d(TAGWallpaperDrawable.setBitmap(位图)); mBitmap =位图; 如果(mBitmap == NULL){ Log.d(TAGWallpaperDrawable.setBitmap(位图)mBitmap ==空); 返回; } mIntrinsicWidth = mBitmap.getWidth(); mIntrinsicHeight = mBitmap.getHeight(); } @覆盖 公共无效画(油画画布){ 如果(mBitmap == NULL){ Log.d(TAGWallpaperDrawable.draw(Canvas)的mBitmap ==空); 返回; } Log.d(TAGWallpaperDrawable.draw(画布)); INT宽度= canvas.getWidth(); INT高度= canvas.getHeight(); INT X =(宽 - mIntrinsicWidth)/ 2; INT Y =(身高 - mIntrinsicHeight)/ 2; canvas.drawBitmap(mBitmap,X,Y,NULL); } @覆盖 公众诠释getOpacity(){ 返回android.graphics.PixelFormat.OPAQUE; } @覆盖 公共无效setAlpha(INT阿尔法){ } @覆盖 公共无效setColorFilter(ColorFilter CF){ }}}
解决方案
运行API 16真正的设备与硬件加速渲染的唯一设备,这就是为什么它的行为不同。你可以尝试设置的android:hardwareAccelerated =您的活动的清单项假这个实验
当您更改的内容,你可以离开,如果你调用invalidateSelf()上加速绘制对象:
私有静态类WallpaperDrawable扩展可绘制{ 无效setBitmap(位图位图){ 。 。 。 invalidateSelf(); }}
I've adapted the code from AOSP "Launcher2" WallpaperChooser & WallpaperChooserDialogFragment to be a standalone Gallery App, and I wanted it to work on API levels 7 up to API 16.
To make it work for API levels < 11 I added the Android Support Library (rev.10) "Compability Package", V4 package.
I based my changes in the compability package (android.support.v4.app.DialogFragment.java) on the suggestions from here: DialogFragments with devices api level < 11.
Otherwise the app would crash with an error ("DialogFragment can not be attached to a container view").
However, the app refuses to work as intended when deployed to an actual Jelly Bean 4.1.1 device (Nexus S), but it works perfectly fine on the emulator.
Tested & Works on:
Android 2.1 Emulator (API 7) Android 2.2 Emulator (API 8) Android 2.3.3 Emulator (API 10) Android 4.0.3 Emulator (API 15)Android 4.1 Emulator (API 16)
Android 2.3.7 Device (API 10)
Tested & Doesn't Work on:
Android 4.1.1 Device (API 16)When running on the 4.1.1 device, it never loads/displays the gallery images when tapping on them in the horizontal view.
It only displays each picture after selecting and rotating the device, and then again, select a new picture, rotate again, and it displays correctly.
I haven't managed to figure out the problem why it wouldn't work on a real device so any help is appreciated. If I remove the compability package and only targets API level +11, the app works on the real 4.1.1 device.
This is the code for the app:
GalleryDemo.java:
package gallery.android.demo;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
public class GalleryDemo extends FragmentActivity {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.wallpaper_chooser_base);
Fragment fragmentView = getSupportFragmentManager().findFragmentById(R.id.wallpaper_chooser_fragment);
if (fragmentView == null) {
DialogFragment fragment = GalleryDemoDialogFragment.newInstance();
fragment.show(getSupportFragmentManager(), "dialog");
}
}
}
GalleryDemoDialogFragment.java:
package gallery.android.demo;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.annotation.TargetApi;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.SpinnerAdapter;
import android.widget.Toast;
import java.util.ArrayList;
@SuppressWarnings("deprecation")
@TargetApi(16)
public class GalleryDemoDialogFragment extends DialogFragment implements AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
private static final String TAG = "GalleryDemoDialogFragment";
private static final String EMBEDDED_KEY = "gallery.android.demo.GalleryDemoDialogFragment.EMBEDDED_KEY";
private boolean mEmbedded;
private Bitmap mBitmap = null;
private ArrayList<Integer> mThumbs;
private ArrayList<Integer> mImages;
private WallpaperLoader mLoader;
private WallpaperDrawable mWallpaperDrawable = new WallpaperDrawable();
public static GalleryDemoDialogFragment newInstance() {
GalleryDemoDialogFragment fragment = new GalleryDemoDialogFragment();
fragment.setCancelable(true);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null && savedInstanceState.containsKey(EMBEDDED_KEY)) {
mEmbedded = savedInstanceState.getBoolean(EMBEDDED_KEY);
} else {
mEmbedded = isInLayout();
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(EMBEDDED_KEY, mEmbedded);
}
private void cancelLoader() {
if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
mLoader.cancel(true);
mLoader = null;
}
}
@Override
public void onDetach() {
super.onDetach();
cancelLoader();
}
@Override
public void onDestroy() {
super.onDestroy();
cancelLoader();
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
FragmentActivity activity = getActivity();
if (activity != null) {
activity.finish();
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
findWallpapers();
return null;
}
@TargetApi(16)
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
findWallpapers();
if (mEmbedded) {
View view = inflater.inflate(R.layout.wallpaper_chooser, container, false);
switch (Build.VERSION.SDK_INT) {
case Build.VERSION_CODES.ICE_CREAM_SANDWICH :
view.setBackgroundDrawable(mWallpaperDrawable);
break;
case Build.VERSION_CODES.JELLY_BEAN :
view.setBackground(mWallpaperDrawable);
break;
default:
view.setBackgroundDrawable(mWallpaperDrawable);
break;
}
final Gallery gallery = (Gallery) view.findViewById(R.id.gallery);
gallery.setCallbackDuringFling(false);
gallery.setOnItemSelectedListener(this);
gallery.setAdapter(new ImageAdapter(getActivity()));
View setButton = view.findViewById(R.id.set);
setButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
int position = gallery.getSelectedItemPosition();
String[] wallpaperArray = getResources().getStringArray(R.array.wallpapers);
String name = wallpaperArray[position]+".jpg";
Log.i(TAG, "Position="+position);
Log.i(TAG, "Filename="+name);
Toast.makeText(getActivity().getApplicationContext(), "(Save2SD)n"+
"Position="+position+"n"+
"Filename="+name+
"", Toast.LENGTH_SHORT).show();
}
});
return view;
}
return null;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
mLoader.cancel();
}
Log.d(TAG, "onItemSelected()");
mLoader = (WallpaperLoader) new WallpaperLoader().execute(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
private void findWallpapers() {
mThumbs = new ArrayList<Integer>(24);
mImages = new ArrayList<Integer>(24);
final Resources resources = getResources();
final String packageName = resources.getResourcePackageName(R.array.wallpapers);
addWallpapers(resources, packageName, R.array.wallpapers);
addWallpapers(resources, packageName, R.array.extra_wallpapers);
}
private void addWallpapers(Resources resources, String packageName, int list) {
final String[] extras = resources.getStringArray(list);
for (String extra : extras) {
int res = resources.getIdentifier(extra, "drawable", packageName);
if (res != 0) {
final int thumbRes = resources.getIdentifier(extra + "_small", "drawable", packageName);
if (thumbRes != 0) {
mThumbs.add(thumbRes);
mImages.add(res);
}
}
}
}
private class ImageAdapter extends BaseAdapter implements ListAdapter, SpinnerAdapter {
private LayoutInflater mLayoutInflater;
ImageAdapter(FragmentActivity activity) {
mLayoutInflater = activity.getLayoutInflater();
}
public int getCount() {
return mThumbs.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view = mLayoutInflater.inflate(R.layout.wallpaper_item, parent, false);
} else {
view = convertView;
}
ImageView iv = (ImageView) view.findViewById(R.id.wallpaper_image);
int thumbRes = mThumbs.get(position);
iv.setImageResource(thumbRes);
Drawable thumbDrawable = iv.getDrawable();
if (thumbDrawable != null) {
thumbDrawable.setDither(true);
} else {
Log.e(TAG, "Error decoding thumbnail resId=" + thumbRes + " for wallpaper #" + position);
}
return view;
}
}
private class WallpaperLoader extends AsyncTask<Integer, Void, Bitmap> {
BitmapFactory.Options mOptions;
WallpaperLoader() {
mOptions = new BitmapFactory.Options();
mOptions.inDither = false;
mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
}
@Override
protected Bitmap doInBackground(Integer... params) {
if (isCancelled()) return null;
try {
return BitmapFactory.decodeResource(getResources(), mImages.get(params[0]), mOptions);
} catch (OutOfMemoryError e) {
return null;
}
}
@Override
protected void onPostExecute(Bitmap b) {
if (b == null) return;
if (!isCancelled() && !mOptions.mCancel) {
if (mBitmap != null) {
mBitmap.recycle();
}
View v = getView();
if (v != null) {
Log.d(TAG, "WallpaperLoader.onPostExecute() getView != null");
mBitmap = b;
mWallpaperDrawable.setBitmap(b); // Doesn't appear to work on (physical) device with Jelly Bean (4.1.1)?
v.postInvalidate();
} else {
Log.d(TAG, "WallpaperLoader.onPostExecute(Bitmap b) getView == null");
mBitmap = null;
mWallpaperDrawable.setBitmap(null);
}
mLoader = null;
} else {
b.recycle();
}
}
void cancel() {
mOptions.requestCancelDecode();
super.cancel(true);
}
}
private static class WallpaperDrawable extends Drawable {
Bitmap mBitmap;
int mIntrinsicWidth;
int mIntrinsicHeight;
void setBitmap(Bitmap bitmap) {
Log.d(TAG, "WallpaperDrawable.setBitmap(Bitmap)");
mBitmap = bitmap;
if (mBitmap == null) {
Log.d(TAG, "WallpaperDrawable.setBitmap(Bitmap) mBitmap == null");
return;
}
mIntrinsicWidth = mBitmap.getWidth();
mIntrinsicHeight = mBitmap.getHeight();
}
@Override
public void draw(Canvas canvas) {
if (mBitmap == null) {
Log.d(TAG, "WallpaperDrawable.draw(Canvas) mBitmap == null");
return;
}
Log.d(TAG, "WallpaperDrawable.draw(Canvas)");
int width = canvas.getWidth();
int height = canvas.getHeight();
int x = (width - mIntrinsicWidth) / 2;
int y = (height - mIntrinsicHeight) / 2;
canvas.drawBitmap(mBitmap, x, y, null);
}
@Override
public int getOpacity() {
return android.graphics.PixelFormat.OPAQUE;
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(ColorFilter cf) {
}
}
}
解决方案
The real device running API 16 is the only device with hardware accelerated rendering, which is why it behaves differently. You can try setting android:hardwareAccelerated="false" in your activity's manifest entry to experiment with this.
You can leave acceleration on if you call invalidateSelf() when you change the content of a Drawable:
private static class WallpaperDrawable extends Drawable {
void setBitmap(Bitmap bitmap) {
. . .
invalidateSelf();
}
}
相关推荐
最新文章