- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我注意到来自 google play store 的其他拼图应用最多可以有 400 个独立的可移动拼图 block
我一直在尝试学习如何至少拍摄一张能代表我的谜题的图像,裁剪某些部分并用拼图设计掩盖图像空间,以创建我的个人拼图
我想为我的应用程序最多使用 20 block ,但到目前为止,根据我的 android studio 内存日志,一旦位图工厂完成创建一个拼图 block ,在创建 20 block 拼图后,我用掉了大约 18mb 的内存该应用程序的所有其他功能我正在使用 400+mb 的内存,我必须使用“largeHeap=true”来防止内存不足,但我已经接近超过这些更高的限制,所以该应用程序非常棒缓慢而足够的动画 Activity 将不可避免地导致应用程序崩溃
我很想知道那些其他 Play 商店益智应用在做什么而我没有做
非常感谢任何输入
仅供引用,我的图像使用 PNG24,测试图像的尺寸为 556x720
这是一个例子,如果我只创建一个动画拼图图片
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);//Remove title bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//Hides notification bar
this.setContentView(R.layout.activity_main);//set content view AFTER ABOVE sequence (to avoid crash)
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
mainDisplay = getWindowManager().getDefaultDisplay();
mainLayout = (ViewGroup) findViewById(R.id.id_layout);
DisplayMetrics m = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(m);
int windowHeight = m.heightPixels;
int windowWidth = m.widthPixels;
offsetX = (windowWidth / 1440.0f);
offsetY = (windowHeight / 2560.0f);
ourContext = this;
xpos = new float[2];
ypos = new float[2];
iv_PuzzleOne();
bkgdbm = BitmapFactory.decodeResource(getResources(), R.drawable.puzzleimage);
paintObject = new Paint();
paintObject.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
bm_PuzzleOne();
thisTimerTask = new ThisClass();
thisTimer = new Timer();
thisTimer.scheduleAtFixedRate(thisTimerTask, 16, 16);
touchpad = new ImageButton(this);
SetPos(0, 0, 1440, 2560);
touchpad.setLayoutParams(layoutPositioner);
touchpad.getBackground().setAlpha(1);
mainLayout.addView(touchpad);
touchpad.setOnTouchListener(new View.OnTouchListener() {
//@SuppressLint("NewApi")
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
xpos[0] = event.getX(); //storing my finger's position coordinates when I first touch the screen into the 1st element
ypos[0] = event.getY();
if ((event.getX() > imgx1) && (event.getX() < imgx1 + imagewidth1)
&& (event.getY() > imgy1) && (event.getY() < imgy1 + imageheight1)) {
touching1Puzzle = true;
img1.bringToFront();
}
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
xpos[1] = event.getX(); //add my finger's new current coordinates into the 2nd element
ypos[1] = event.getY();
if (touching1Puzzle) {
adjustImg();
}
}
if (event.getAction() == MotionEvent.ACTION_UP) {
if (touching1Puzzle) {
touching1Puzzle = false;
}
}
return false;
}
});
}
void bm_PuzzleOne()
{
//start of 1st puzzle
foregdimg1 = BitmapFactory.decodeResource(getResources(), R.drawable.puzzlepieceprac);//puzzle cut out (42.48MB) +6.15
mutableforegdimg1 = foregdimg1.copy(Bitmap.Config.ARGB_8888, true); //(48.32MB) +5.84
compositeImage1 = Bitmap.createBitmap(mutableforegdimg1);//cuts out foreground info into bkgdimage (54.43MB) +6.11
imgCanvas1 = new Canvas(compositeImage1); //canvas references puzzle cut out image (54.43MB) +0
imgCanvas1.drawBitmap(croppedBmp, null, new Rect(0, 0, 1500, 2000), paintObject);//places puzzle image on canvas (54.43MB) +0
img1.setImageBitmap(compositeImage1);
}
void iv_PuzzleOne()
{
img1 = new ImageView(ourContext);
SetPos(imgx1, imgy1, imagewidth1, imageheight1);
//bkgdimg.setImageResource(R.drawable.c);
//img1.setBackgroundColor(0xffF07305); //Orange
img1.setLayoutParams(layoutPositioner);
mainLayout.addView(img1);
}
void adjustImg()
{
if (touching1Puzzle)
{
if (xpos[1] > xpos[0]) //if the image had slid to the right
{
xPositionDifference = xpos[1] - xpos[0]; // find the difference in coordinate value between where my finger was and where it currently is
imgx1 += xPositionDifference; //add that difference to the current image position ...
xpos[0] += xPositionDifference; // ... store that difference for the next shift in finger postion
} else if (xpos[1] < xpos[0]) //if the image had slid to the left
{
xPositionDifference = xpos[0] - xpos[1]; // find the difference in coordinate value between where my finger was and where it currently is
imgx1 -= xPositionDifference; //subtract that difference to the current image position ...
xpos[0] -= xPositionDifference; // ... store that difference for the next shift in finger postion
}
if (ypos[1] > ypos[0]) //if the image had slid to the right
{
yPositionDifference = ypos[1] - ypos[0]; // find the difference in coordinate value between where my finger was and where it currently is
imgy1 += yPositionDifference; //add that difference to the current image position ...
ypos[0] += yPositionDifference; // ... store that difference for the next shift in finger postion
} else if (ypos[1] < ypos[0]) //if the image had slid to the left
{
yPositionDifference = ypos[0] - ypos[1]; // find the difference in coordinate value between where my finger was and where it currently is
imgy1 -= yPositionDifference; //subtract that difference to the current image position ...
ypos[0] -= yPositionDifference; // ... store that difference for the next shift in finger postion
}
}
}
class ThisClass extends TimerTask {
@Override
public void run() {
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if(touching1Puzzle)
{SetPos(imgx1, imgy1, imagewidth1, imageheight1);
img1.setLayoutParams(layoutPositioner);}
}
});
}
}
public void SetPos(float x, float y, float width, float height) {
layoutPositioner = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutPositioner.topMargin = (int) (offsetY * y);
layoutPositioner.leftMargin = (int) (offsetX * x);
layoutPositioner.width = (int) (width * offsetX);
layoutPositioner.height = (int) (height * offsetY);
}
这是我加载 5 张图片时的样子
http://s15.postimg.org/ymqspk77v/Screenshot_2016_02_29_07_19_26.png
最佳答案
好吧,让我们看看。
首先你不需要这么大的拼图,所以你可以缩小它们:
来自 http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
To tell the decoder to subsample the image, loading a smaller version into memory, set inSampleSize to true in your BitmapFactory.Options object. For example, an image with resolution 2048x1536 that is decoded with an inSampleSize of 4 produces a bitmap of approximately 512x384. Loading this into memory uses 0.75MB rather than 12MB for the full image (assuming a bitmap configuration of ARGB_8888)
其次,您应该尝试在 AsyncTask 中加载位图以防止应用程序卡住。
第三,您可以使用 LruCache 缓存您的位图以加快速度
http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
private LruCache<String, Bitmap> mMemoryCache;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// Get max available VM memory, exceeding this amount will throw an
// OutOfMemory exception. Stored in kilobytes as LruCache takes an
// int in its constructor.
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// Use 1/8th of the available memory for this memory cache.
final int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// The cache size will be measured in kilobytes rather than
// number of items.
return bitmap.getByteCount() / 1024;
}
};
...
}
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
mMemoryCache.put(key, bitmap);
}
}
public Bitmap getBitmapFromMemCache(String key) {
return mMemoryCache.get(key);
}
这应该足够了,但如果还不够的话,这里有所有来源,还有一些额外的: http://developer.android.com/training/displaying-bitmaps/index.html
你也可以尝试使用
void bm_PuzzleOne()
{
//start of 1st puzzle
BitmapFactory.Options opt = new BitmapFactory.Options();
//makes a loaded image mutable
opt.inMutable=true;
//reduces density to that of screen
opt.inTargetDensity = this.context.getResources().getDisplayMetrics().densityDpi;
opt.inScaled=true;
//makes bitmap half as big
opt.inSampleSize=2;
//foregdimg1 = BitmapFactory.decodeResource(getResources(), R.drawable.puzzlepieceprac);//puzzle cut out (42.48MB) +6.15
mutableforegdimg1 = BitmapFactory.decodeResource(getResources(), R.drawable.puzzlepieceprac,opt)
compositeImage1 = Bitmap.createBitmap(mutableforegdimg1);//cuts out foreground info into bkgdimage (54.43MB) +6.11
imgCanvas1 = new Canvas(compositeImage1); //canvas references puzzle cut out image (54.43MB) +0
imgCanvas1.drawBitmap(croppedBmp, null, new Rect(0, 0, 1500, 2000), paintObject);//places puzzle image on canvas (54.43MB) +0
img1.setImageBitmap(compositeImage1);
}
代替
void bm_PuzzleOne()
{
//start of 1st puzzle
foregdimg1 = BitmapFactory.decodeResource(getResources(), R.drawable.puzzlepieceprac);//puzzle cut out (42.48MB) +6.15
mutableforegdimg1 = foregdimg1.copy(Bitmap.Config.ARGB_8888, true); //(48.32MB) +5.84
compositeImage1 = Bitmap.createBitmap(mutableforegdimg1);//cuts out foreground info into bkgdimage (54.43MB) +6.11
imgCanvas1 = new Canvas(compositeImage1); //canvas references puzzle cut out image (54.43MB) +0
imgCanvas1.drawBitmap(croppedBmp, null, new Rect(0, 0, 1500, 2000), paintObject);//places puzzle image on canvas (54.43MB) +0
img1.setImageBitmap(compositeImage1);
}
关于android - 如何在不耗尽内存的情况下在 droid 中制作益智应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35706406/
我是 Java 新手,这是我的代码, if( a.name == b.name && a.displayname == b.displayname && a.linknam
在下面的场景中,我有一个 bool 值。根据结果,我调用完全相同的函数,唯一的区别是参数的数量。 var myBoolean = ... if (myBoolean) { retrieve
我是一名研究 C++ 的 C 开发人员: 我是否正确理解如果我抛出异常然后堆栈将展开直到找到第一个异常处理程序?是否可以在不展开的情况下在任何 throw 上打开调试器(即不离开声明它的范围或任何更高
在修复庞大代码库中的错误时,我观察到一个奇怪的情况,其中引用的动态类型从原始 Derived 类型更改为 Base 类型!我提供了最少的代码来解释问题: struct Base { // some
我正在尝试用 C# 扩展给定的代码,但由于缺乏编程经验,我有点陷入困境。 使用 Visual Studio 社区,我尝试通过控制台读出 CPU 核心温度。该代码使用开关/外壳来查找传感器的特定名称(即
这可能是一个哲学问题。 假设您正在向页面发出 AJAX 请求(这是使用 Prototype): new Ajax.Request('target.asp', { method:"post", pa
我有以下 HTML 代码,我无法在所有浏览器中正常工作: 我试图在移动到
我对 Swift 很陌生。我如何从 addPin 函数中检索注释并能够在我的 addLocation 操作 (buttonPressed) 中使用它。我正在尝试使用压力触摸在 map 上添加图钉,在两
我设置了一个详细 View ,我是否有几个 Nib 文件根据在 Root View Controller 的表中选择的项目来加载。 我发现,对于 Nibs 的类,永远不会调用 viewDidUnloa
我需要动态访问 json 文件并使用以下代码。在本例中,“bpicsel”和“temp”是变量。最终结果类似于“data[0].extit1” var title="data["+bpicsel+"]
我需要使用第三方 WCF 服务。我已经在我的证书存储中配置了所需的证书,但是在调用 WCF 服务时出现以下异常。 向 https://XXXX.com/AHSharedServices/Custome
在几个 SO 答案(1、2)中,建议如果存在冲突则不应触发 INSERT 触发器,ON CONFLICT DO NOTHING 在触发语句中。也许我理解错了,但在我的实验中似乎并非如此。 这是我的 S
如果进行修改,则会给出org.hibernate.NonUniqueObjectException。在我的 BidderBO 类(class)中 @Override @Transactional(pr
我使用 indexOf() 方法来精细地查找数组中的对象。 直到此刻我查了一些资料,发现代码应该无法正常工作。 我在reducer中尝试了上面的代码,它成功了 let tmp = state.find
假设我有以下表格: CREATE TABLE Game ( GameID INT UNSIGNED NOT NULL, GameType TINYINT UNSIGNED NOT NU
代码: Alamofire.request(URL(string: imageUrl)!).downloadProgress(closure: { (progress) in
我是一名优秀的程序员,十分优秀!