本文介绍了SurfaceView返回droidreader黑色屏幕的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我有很多与放审判;甚至很多搜索,但我没有找到关于在黑屏解决方案我获得通过获取的表面观缓存观点..如果有任何其他的方式来捕捉画面,然后让我知道这个..如果我用另一个控制及;获取该控件也返回null的绘制缓存..这是code这是我用来获取屏幕图像.... {尝试 //按钮BTN =新按钮(mActivity.getApplicationContext()); view.buildDrawingCache(); view.setDrawingCacheEnabled(真); 位图B = view.getDrawingCache(); b.com preSS(比较pressFormat.JPEG,100,新的FileOutputStream( 到/ mnt / SD卡/文件/+新的Date()的getTime()+.JPEG));}赶上(例外五){ e.printStackTrace();} 我已经在表面观的touch_up动作用这个..... 编辑: 公共类DroidReaderActivity延伸活动{私有静态最终布尔LOG = FALSE;私有静态最终诠释REQUEST_ code_PICK_FILE = 1;私有静态最终诠释REQUEST_ code_OPTION_DIALOG = 2;私有静态最终诠释DIALOG_GET_PASSWORD = 1;私有静态最终诠释DIALOG_ABOUT = 2;私有静态最终诠释DIALOG_GOTO_PAGE = 3;私有静态最终诠释DIALOG_WELCOME = 4;私有静态最终诠释DIALOG_ENTER_ZOOM = 5;私有静态最后弦乐preFERENCE_EULA_ACCEPTED =eula.accepted;私有静态最后弦乐preFERENCES_EULA =最终用户许可协议;保护DroidReaderView mReaderView = NULL;保护DroidReaderDocument mDocument = NULL;保护菜单m_ZoomMenu;佛罗里达州的FrameLayout;私人字符串mFilename;私人字符串mTemporaryFilename;私人字符串mPassword;私人诠释mPageNo;私人SQLiteDatabase分贝;静态DatabaseConnectionAPI db_api;私人布尔mDocumentIsOpen = FALSE;私人布尔mLoadedDocument = FALSE;私人布尔mWelcomeShown = FALSE;@覆盖保护无效的onActivityResult(INT申请code,INT结果code,意图数据){ super.onActivityResult(要求code,结果code,数据); 开关(要求code){ 案例REQUEST_ code_PICK_FILE: 如果(结果code == RESULT_OK&放大器;&放大器;数据!= NULL){ //理论上有可能是在那里的OnCreate()被调用的情况下 //再与原本是用来打开应用程序的意图, //这将恢复到previous文件。使用setIntent //更新将被供给回的OnCreate的意图()。 setIntent(数据); mTemporaryFilename = data.getDataString(); 如果(mTemporaryFilename!= NULL){ 如果(mTemporaryFilename.startsWith(文件://)){ mTemporaryFilename = mTemporaryFilename.substring(7); } mPassword =; openDocumentWithDe codeAndLookup(); } } 打破; 案例REQUEST_ code_OPTION_DIALOG: 阅读preferences(); tryLoadLastFile(); 打破; }}/ **当第一次创建活动调用。 * /@覆盖公共无效的onCreate(捆绑savedInstanceState){ super.onCreate(savedInstanceState); 的System.out.println(在OnCreate); db_api =新DatabaseConnectionAPI(本); 尝试{ db_api.createDataBase(); db_api.openDataBase(); }赶上(IOException异常五){ e.printStackTrace(); } //首先,显示欢迎,如果尚未已经显示出它: 最后一个共享preferences preferences = getShared preferences(preFERENCES_EULA,Context.MODE_PRIVATE); 如果(!preferences.getBoolean(preFERENCE_EULA_ACCEPTED,FALSE)){ mWelcomeShown = TRUE; preferences.edit()putBoolean(preFERENCE_EULA_ACCEPTED,真).commit()。 的ShowDialog(DIALOG_WELCOME); } 如果(mDocument == NULL) mDocument =新DroidReaderDocument(); //初始化PdfRender引擎 PdfRender.setFontProvider(新DroidReaderFontProvider(本)); //然后建立我们的布局。它是如此简单,我们不使用 // XML现在。 FL =新的FrameLayout(本); mReaderView =新DroidReaderView(这一点,空,mDocument); //添加观看区和导航 fl.addView(mReaderView); 的setContentView(佛罗里达州); 阅读preferences(); 如果(savedInstanceState!= NULL){ mFilename = savedInstanceState.getString(文件名); 如果((新文件(mFilename))。存在()){ mPassword = savedInstanceState.getString(密码); mDocument.mZoom = savedInstanceState.getFloat(缩放); mDocument.mRotation = savedInstanceState.getInt(旋转); mPageNo = savedInstanceState.getInt(页); mDocument.mMarginOffsetX = savedInstanceState.getInt(marginOffsetX); mDocument.mMarginOffsetY = savedInstanceState.getInt(marginOffsetY); mDocument.mContentFitMode = savedInstanceState.getInt(contentFitMode); 使用openDocument(); mLoadedDocument =真; } savedInstanceState.clear(); } 定时器mTimer =新的Timer(); mTimer.schedule(新的TimerTask(){ @覆盖 公共无效的run(){ 尝试{ 位图saveBitmap = Bitmap.createBitmap(fl.getWidth(),fl.getHeight(),Bitmap.Config.ARGB_8888); saveBitmap.com preSS(比较pressFormat.JPEG,100, 新的FileOutputStream(到/ mnt / SD卡/文件/+新的Date()的getTime()+.JPEG)); }赶上(例外五){ e.printStackTrace(); } } },4000); }}@覆盖保护无效的onSaveInstanceState(捆绑outState){ super.onSaveInstanceState(outState); 如果((mDocument = NULL)及!&安培; mDocument.isPageLoaded()){ outState.putFloat(放大,mDocument.mZoom); outState.putInt(旋转,mDocument.mRotation); outState.putInt(页,mDocument.mPage.no); outState.putInt(offsetX,mDocument.mOffsetX); outState.putInt(offsetY,mDocument.mOffsetY); outState.putInt(marginOffsetX,mDocument.mMarginOffsetX); outState.putInt(marginOffsetY,mDocument.mMarginOffsetY); outState.putInt(contentFitMode,mDocument.mContentFitMode); outState.putString(密码,mPassword); outState.putString(文件名,mFilename); mDocument.closeDocument(); }}公共无效的onTap(浮法X,浮法Y){ 浮动左,右,上,下; 浮动宽度= mDocument.mDisplaySizeX; 浮动高度= mDocument.mDisplaySizeY; 布尔preV = FALSE; 布尔下一= FALSE; 如果(mDocumentIsOpen){ 左=宽*(浮点)0.25; 右=宽*(浮点)0.75; 顶部=身高*(浮点)0.25; 底=身高*(浮点)0.75; 如果((X LT;左)及及(Y'LT;顶)) preV =真实的; 如果((X LT;左)及及(Y'GT;底部)) 接下来= TRUE; 如果((X GT;右)及及(Y'LT;顶)) preV =真实的; 如果((X GT;右)及及(Y'GT;底部)) 接下来= TRUE; 如果((X GT;左)及及(X'LT;右)及及(Y'GT;底部)){ Log.d(DroidReaderMetrics的String.format(变焦=%5.2f %%,mDocument.mZoom * 100.0)); Log.d(DroidReaderMetrics的String.format(页面大小=(%2.0F,2.0F%),mDocument.mPage.mMediabox [2] - mDocument.mPage.mMediabox [0],mDocument.mPage.mMediabox [3] - mDocument.mPage.mMediabox [1])); Log.d(DroidReaderMetrics的String.format( 显示大小=(%D,%D),mDocument.mDisplaySizeX,mDocument.mDisplaySizeY)); Log.d(DroidReaderMetrics的String.format(DPI =(%D,%D),mDocument.mDpiX,mDocument.mDpiY)); Log.d(DroidReaderMetrics的String.format(内容大小=(%2.0F,2.0F%), mDocument.mPage.mContentbox [2] - mDocument.mPage.mContentbox [0], mDocument.mPage.mContentbox [3] - mDocument.mPage.mContentbox [1])); Log.d(DroidReaderMetrics的String.format(内容偏移量=(%2.0F,2.0F%), mDocument.mPage.mContentbox [0],mDocument.mPage.mContentbox [1])); Log.d(DroidReaderMetrics的String.format( 文档偏移量=(%D,%D),mDocument.mOffsetX,mDocument.mOffsetY)); } 如果(下){ 如果(mDocument.havePage(1,真)) openPage(1,真); }否则如果(preV){ 如果(mDocument.havePage(-1,真)) openPage(-1,真); } }}保护无效使用openDocument(){ //保存为previous文档的查看详情并关闭它。 如果(mDocumentIsOpen){ mDocument.closeDocument(); mDocumentIsOpen = FALSE; } 尝试{ this.setTitle(mFilename); mDocument.open(mFilename,mPassword,mPageNo); openPage(0,真); mDocumentIsOpen = TRUE; }赶上(PasswordNeededException E){ 的ShowDialog(DIALOG_GET_PASSWORD); }赶上(WrongPasswordException E){ Toast.makeText(这一点,R.string.error_wrong_password,Toast.LENGTH_LONG).show(); }赶上(例外五){ Toast.makeText(这一点,R.string.error_opening_document,Toast.LENGTH_LONG).show(); }}保护无效openDocumentWithDe codeAndLookup(){ 尝试{ mTemporaryFilename = URLDe coder.de code(mTemporaryFilename,UTF-8); //请在所提供的一些文件名完整性检查。 文件f =新的文件(mTemporaryFilename); 如果((f.exists())及及(f.isFile())及及(f.canRead())){ mFilename = mTemporaryFilename; openDocumentWithLookup(); }其他{ Toast.makeText(这一点,R.string.error_file_open_failed,Toast.LENGTH_LONG).show(); } }赶上(例外五){ Toast.makeText(这一点,R.string.error_opening_document,Toast.LENGTH_LONG).show(); }}保护无效openDocumentWithLookup(){ readOrWriteDB(假); 使用openDocument();}保护无效openPage(int无,布尔而isRelative){ 尝试{ 如果((没有== 0安培;!&安培;而isRelative)) mDocument.openPage(无,而isRelative); this.setTitle(新文件(mFilename).getName() +的String.format((%D /%D),mDocument.mPage.no,mDocument.mDocument.pagecount)); mPageNo = mDocument.mPage.no; }赶上(PageLoadException E){ }}私人无效读取preferences(){ 共享preferences preFS = preferenceManager.getDefaultShared preferences(本); DisplayMetrics指标=新DisplayMetrics(); 。getWindowManager()getDefaultDisplay()getMetrics(指标)。 如果(prefs.getString(zoom_type,0)。等于(0)){ 浮动变焦= Float.parseFloat(prefs.getString(zoom_percent,50)); 如果((1 mDocument.setZoom(变焦/ 100,FALSE); } }其他{ mDocument.setZoom(Float.parseFloat(prefs.getString(zoom_type,0)),假); } 如果(prefs.getBoolean(dpi_auto,真)){ //读取显示的DPI mDocument.setDpi((INT)metrics.xdpi,(INT)metrics.ydpi); }其他{ INT DPI =的Integer.parseInt(prefs.getString(dpi_manual,160)); 如果((DPI&LT; 1)||(DPI&GT; 4096)) DPI = 160; //完整性检查备用 mDocument.setDpi(DPI,DPI); } 如果(prefs.getBoolean(tilesize_by_factor,真)){ //设置瓷砖的大小由系数呈现 浮动系数= Float.parseFloat(prefs.getString(tilesize_factor,1.5)); mDocument.setTileMax((int)的(metrics.widthPixels *因子),(INT)(metrics.heightPixels *因子)); }其他{ INT tilesize_x =的Integer.parseInt(prefs.getString(tilesize_x,640)); INT tilesize_y =的Integer.parseInt(prefs.getString(tilesize_x,480)); 如果(metrics.widthPixels&LT; metrics.heightPixels){ mDocument.setTileMax(tilesize_x,tilesize_y); }其他{ mDocument.setTileMax(tilesize_y,tilesize_x); } } 布尔反转= prefs.getBoolean(invert_display,FALSE); mDocument.setDisplayInvert(反转); mReaderView.setDisplayInvert(反转); 如果(prefs.getBoolean(FULL_SCREEN,FALSE)){ 。this.getWindow()addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); }其他{ 。this.getWindow()clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } mDocument.mHorizontalScrollLock = prefs.getBoolean(horizontal_scroll_lock,FALSE);}保护无效setZoom(浮动newZoom){ newZoom = newZoom /(浮点)100.0; 如果(newZoom&GT; 16.0) newZoom =(浮点)16.0; 如果(newZoom&LT; 0.0625) newZoom =(浮点)0.0625; mDocument.setZoom(newZoom,FALSE);}保护无效tryLoadLastFile(){ 共享preferences preFS = preferenceManager.getDefaultShared preferences(本); mFilename = prefs.getString(last_open_file,); 如果(mFilename!= NULL){ 如果((mFilename.length()大于0)及与放大器;((新文件(mFilename))存在())){ //不要URL德code中的文件名,因为这是presumably已经完成。 mPassword =; openDocumentWithLookup(); mLoadedDocument =真; } }}} DroidReaderView: 公共类DroidReaderView扩展SurfaceView实现OnGestureListener, SurfaceHolder.Callback,DroidReaderDocument.RenderListener {公共静态路径的mpath =新路径();私有静态StringBuffer的SBX =新的StringBuffer();私有静态的StringBuffer SBY =新的StringBuffer();公共静电漆mPaint =新的油漆();公共静电漆nullpaint =新的油漆();私人字符串SX,SY,sbx_str,sby_str;公共静态帆布mCanvas =新的Canvas();私人INT PID = 1;/ ** *调试助手 * /保护最终静态字符串变量=DroidReaderView;保护最终静态布尔LOG = FALSE;/ ** *我们认为这线程做绘图 * /公共DroidReaderViewThread mThread;/ ** *我们的姿态探测器 * /保护最终GestureDetector mGestureDetector;/ ** *我们的语境 * /保护最终DroidReaderActivity mActivity;/ ** *我们SurfaceHolder * /保护最终SurfaceHolder mSurfaceHolder;公共静态DroidReaderDocument mDocument;保护布尔mDisplayInvert;/ ** *构造一个新的View * * @参数方面 *语境。查看 * @参数ATTRS *属性(可以为null) * /公共DroidReaderView(最终DroidReaderActivity活动的AttributeSet ATTRS,DroidReaderDocument文件){ 超(活动,ATTRS); mActivity =活动; mSurfaceHolder = getHolder(); mDocument =文件; mDocument.mRenderListener =这一点; mPaint.setAntiAlias(真); mPaint.setDither(真); mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(12); //告诉SurfaceHolder,通知此线程 //更改到表面 mSurfaceHolder.addCallback(本); mGestureDetector =新GestureDetector(本);}/ *事件监听器:* /@覆盖保护无效的onDraw(帆布油画){ mThread.c =帆布; mThread.c = mSurfaceHolder.lockCanvas(); mPaint =新的油漆(); mPaint.setAntiAlias(真); mPaint.setDither(真); mPaint.setColor(Color.RED); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(12); mThread.c.drawPath(的mpath,mPaint); mSurfaceHolder.unlockCanvasAndPost(mThread.c);}@覆盖公共布尔onFling(MotionEvent E1,E2 MotionEvent,浮velocityX,浮velocityY){ 如果(LOG) Log.d(TAGonFling():通知ViewThread); mThread.mScroller.fling(0,0, - (INT)velocityX, - (int)的velocityY,-4096,4096,-4096,4096); mThread.triggerRepaint(); 返回true;}/ *键盘事件:* /@覆盖公共布尔的onkeydown(INT键code,味精的KeyEvent){ 如果(LOG) Log.d(TAG的onkeydown(),键code键+ code); 返回false;}@覆盖公共布尔的onkeyup(INT键code,味精的KeyEvent){ 如果(LOG) Log.d(TAG的onkeyup(),键code键+ code); 返回false;}/ *为GestureListener接口:* /@覆盖公共无效onLong preSS(MotionEvent五){ 如果(LOG) Log.d(TAGonLong $ P $(PSS):忽略!);}@覆盖公共无效onNewRenderedPixmap(){ 如果(LOG) Log.d(TAG,新的渲染像素图中信号); mThread.triggerRepaint();}@覆盖公共布尔onScroll(MotionEvent E1,E2 MotionEvent,浮distanceX,浮distanceY){ 如果(LOG) Log.d(TAGonScroll(),距离矢量:+ distanceX +,+ distanceY); mDocument.offset((INT)distanceX,(INT)distanceY,真正的); mThread.triggerRepaint(); 返回true;}@覆盖公共无效昂秀preSS(MotionEvent五){ 如果(LOG) Log.d(TAG,昂秀$ P $(PSS):忽略);}@覆盖公共布尔onSingleTapUp(MotionEvent五){ //传递抽头,和窗口尺寸,到活动处理。 mActivity.onTap(e.getX(),e.getY()); 返回true;}私人浮动MX,我的;私有静态最终浮动TOUCH_TOLERANCE = 4;私人无效touch_start(浮法X,浮法Y){ mPath.moveTo(X,Y); MX = X; SX = Float.toString(MX); sbx.append(SX); sbx.append(,); 我= Y; SY = Float.toString(我的); sby.append(SY) sby.append(,); sbx_str = sbx.toString(); sby_str = sby.toString();}私人无效draw_move(浮法X,浮法Y){ 浮DX = Math.abs(X - MX); 浮DY = Math.abs(Y - 我的); 如果(DX&GT; = || TOUCH_TOLERANCE DY&GT; = TOUCH_TOLERANCE){ mPath.quadTo(MX,MY,(X + MX)/ 2,(Y + MY)/ 2); MX = X; SX = Float.toString(MX); sbx.append(SX); sbx.append(,); 我= Y; SY = Float.toString(我的); sby.append(SY) sby.append(,); }}私人无效touch_up(){ mPath.lineTo(MX,我的); SX = Float.toString(MX); sbx.append(SX); sbx.append(,); SY = Float.toString(我的); sby.append(SY) sby.append(,); mPath.reset(); sbx_str = sbx.toString()修剪()。 sby_str = sby.toString()修剪()。 插入(标签presentation_id,mDocument.mPage.no,sbx_str,sby_str); SBX =新的StringBuffer(); SBY =新的StringBuffer(); 的System.out.println(sbx_str.trim()); 的System.out.println(sby_str.trim());}@覆盖公共布尔onTouchEvent(最终MotionEvent事件){ 浮X = event.getX(); 浮Y = event.getY(); 开关(event.getAction()){ 案例MotionEvent.ACTION_DOWN: touch_start(X,Y); 无效(); 打破; 案例MotionEvent.ACTION_MOVE: draw_move(X,Y); 无效(); 打破; 案例MotionEvent.ACTION_UP: 润色(); 无效(); 尝试{ //按钮BTN =新按钮(mActivity.getApplicationContext()); // buildDrawingCache(); // setDrawingCacheEnabled(真); //位图B = getDrawingCache(); // b.com preSS(比较pressFormat.JPEG,100,新的FileOutputStream( //到/ mnt / SD卡/文件/+新的Date()的getTime()+.JPEG))。 }赶上(例外五){ e.printStackTrace(); } 打破; } 无效(); 如果(LOG){ Log.d(TAGonTouchEvent():通知mGestureDetector); 无效(); } 如果(mGestureDetector.onTouchEvent(事件)){ 无效(); 返回true; } 返回true;}@覆盖公共布尔onTrackballEvent(MotionEvent事件){ 如果(LOG) Log.d(TAGonTouchEvent():通知ViewThread); mDocument .offset((INT)event.getX()* 20,(INT)event.getY()* 20,真正的); mThread.triggerRepaint(); 返回true;}/ *面事件:* /公共无效setDisplayInvert(布尔翻转){ 如果(mThread!= NULL) mThread.setPainters(反转); mDisplayInvert =反转;}@覆盖公共无效surfaceChanged(SurfaceHolder架,INT格式,宽度INT, INT高度){ 如果(LOG) Log.d(TAGsurfaceChanged():大小+宽+X+高); mDocument.startRendering(宽度,高度);}@覆盖公共无效surfaceCreated(SurfaceHolder持有人){ 如果(LOG) Log.d(TAGsurfaceCreated():开始ViewThread); mThread =新DroidReaderViewThread(架,mActivity,mDocument); mThread.setPainters(mDisplayInvert); mThread.start();}/ *渲染事件* /@覆盖公共无效surfaceDestroyed(SurfaceHolder持有人){ 如果(LOG) Log.d(TAGsurfaceDestroyed():垂死); mDocument.sto prendering(); 布尔重试= TRUE; mThread.mRun = FALSE; mThread.interrupt(); 而(重试){ 尝试{ mThread.join(); 重试= FALSE; }赶上(InterruptedException的E){ } }}@覆盖公共布尔onDown(MotionEvent五){ 返回false;} DroidReaderViewThread: 主题是关心块传输像素映射到画布上并处理滚动 类DroidReaderViewThread继承Thread {公共帆布C =新的Canvas();私人光标mCursor;私人路径mpath1,它将=新路径();私人StringBuffer的sbx_read,sby_read;公共静电漆mPaint2 =新的油漆();公共静电漆mPaint3 =新的油漆();路径old_path =新路径();/ ** *调试助手 * /保护最终静态字符串变量=DroidReaderViewThread;保护最终静态布尔LOG = FALSE;/ ** *在SurfaceHolder我们的面 * /保护最终SurfaceHolder mSurfaceHolder;/ ** *页面呈现的(还)没有油漆件 * /保护面漆mEmptyPaint;/ ** *油漆用于填充显示当没有PdfPage(还) * /保护面漆mNoPagePaint;/ ** *涂料状态文本 * /保护面漆mStatusPaint;/ ** *标志,我们的线程应该运行 * /保护布尔mRun = TRUE;/ ** *我们的卷轴 * /保护最后的滚轮mScroller;保护最终DroidReaderDocument mDocument;/ ** *背景渲染线程,使用SurfaceView编程方案 * * @参数架 *我们SurfaceHolder * @参数方面 *框架下我们的绘图 * /公共DroidReaderViewThread(SurfaceHolder架,上下文的背景下,DroidReaderDocument文件){ //保存我们的SurfaceHolder参考 mSurfaceHolder =持有人; mDocument =文件; //初始化非像素图地区涂料 mEmptyPaint =新的油漆(); mNoPagePaint =新的油漆(); mStatusPaint =新的油漆(); setPainters(假); //滚动条,即,计算对象/内插 滚动/跳/ //急张职位 mScroller =新的滚轮(背景);}/ ** * LL这样做实际的绘制到Canvas我们的面 * /私人无效doDraw(){ 如果(LOG) Log.d(TAG,引...); C = NULL; 尝试{ C = mSurfaceHolder.lockCanvas(NULL); 如果(!mDocument.isPageLoaded()){ //没有网页/文件加载 如果(LOG) Log.d(TAG,没有加载页面。); c.drawRect(0,0,c.getWidth(),c.getHeight(),mNoPagePaint); }否则如果(mDocument.havePixmap()){ //我们有页面和像素图,所以得出: //背景: 如果(LOG) Log.d(TAG页面加载,渲染像素图); c.drawRect(0,0,c.getWidth(),c.getHeight(),mEmptyPaint); Log.d(CALL,CALL); c.drawBitmap(mDocument.mView.mBuf,0, mDocument.mView.mViewBox.width(),-mDocument.mOffsetX + mDocument.mView.mViewBox.left, -mDocument.mOffsetY + mDocument.mView.mViewBox.top, mDocument.mView.mViewBox.width(),mDocument.mView.mViewBox.height(),假,空); 尝试{ Log.d(读,读); mCursor = DroidReaderActivity.db_api .ExecuteQueryGetCursor(SELECT * FROM所在的路径page_no =+ mDocument.mPage.no +和presentation_id =+ TAGS presentation_id +;); 如果(!mCursor.equals(NULL)){ mCursor.moveToFirst(); 浮X1 = 0,Y1 = 0; INT PID = 0; 做{ sbx_read =新的StringBuffer(); sbx_read.append(mCursor.getString(mCursor.getColumnIndex(x_path))); sby_read =新的StringBuffer(); sby_read.append(mCursor.getString(mCursor.getColumnIndex(y_path))); 的String [] = sbx_read_array sbx_read.toString()修剪()分裂()。; 的String [] = sby_read_array sby_read.toString()修剪()分裂()。; 的for(int i = 0; I&LT; sbx_read_array.length;我++){ X1 = Float.parseFloat(sbx_read_array [I]的ToString()); Y1 = Float.parseFloat(sby_read_array [I]的ToString()); 如果(PID!= mCursor.getInt(mCursor.getColumnIndex(path_id))){ PID = mCursor.getInt(mCursor.getColumnIndex(path_id)); Log.d(新路径标识。 将String.valueOf(mCursor.getInt(mCursor.getColumnIndex(path_id)))); mPath1.reset(); mPath1.moveTo(X1,Y1); }其他{ Log.d(路径ID重复。 将String.valueOf(mCursor.getInt(mCursor.getColumnIndex(path_id)))); } mPath1.lineTo(X1,Y1); c.drawPath(mpath1,它将,DroidReaderView.mPaint); } }而(mCursor.moveToNext()); mCursor.close(); Log.d(阅读模式完成,阅读模式完成); } }赶上(例外五){ // Log.d(读指针,e.getMessage()的toString()); } }其他{ //加载页面,但目前还没有点阵图 如果(LOG) Log.d(TAG,加载网页,但没有主动像素图); c.drawRect(0,0,c.getWidth(),c.getHeight(),mEmptyPaint); mPaint3.setAntiAlias(真); mPaint3.setDither(真); mPaint3.setColor(Color.TRANSPARENT); mPaint3.setStyle(Paint.Style.STROKE); mPaint3.setStrokeJoin(Paint.Join.ROUND); mPaint3.setStrokeCap(Paint.Cap.ROUND); mPaint3.setStrokeWidth(12); mPaint3.setXfermode(新PorterDuffXfermode(PorterDuff.Mode.CLEAR)); c.drawPath(old_path,mPaint3); } } {最后 如果(C!= NULL){ mPaint2.setAntiAlias(真); mPaint2.setDither(真); mPaint2.setColor(Color.GREEN); mPaint2.setStyle(Paint.Style.STROKE); mPaint2.setStrokeJoin(Paint.Join.ROUND); mPaint2.setStrokeCap(Paint.Cap.ROUND); mPaint2.setStrokeWidth(12); c.drawPath(DroidReaderView.mPath,mPaint2); // DroidReaderView.mPath.reset(); // old_path = DroidReaderView.mPath; } mSurfaceHolder.unlockCanvasAndPost(C); }}/ ** *主线程循环 * /@燮pressWarnings(静态访问)@覆盖公共无效的run(){ 而(mRun){ 布尔doSleep =真; 如果(!mScroller.isFinished()){ 如果(mScroller.computeScrollOffset()){ 如果(LOG) Log.d(TAG,新的滚动偏移); doSleep = FALSE; INT oldX = mDocument.mOffsetX; INT oldY = mDocument.mOffsetY; mDocument.offset(mScroller.getCurrX(),mScroller.getCurrY(),TRUE); 如果((oldX == mDocument.mOffsetX)及及(oldY == mDocument.mOffsetY)) mScroller.abortAnimation(); }其他{ mScroller.abortAnimation(); } } doDraw(); //如果我们允许,我们会去睡觉了 如果(doSleep){ 尝试{ //没事做,等待有人叫我们起床: 如果(LOG) Log.d(TAG,ViewThread睡觉); //之间 //检查待处理中断和睡眠(),它 //可能会导致一个不处理的重画请求: 如果(!this.interrupted()) 视频下载(3600000); }赶上(InterruptedException的E){ 如果(LOG) Log.d(TAGViewThread唤醒); } } } // mRun现在是假的,所以我们关闭。 如果(LOG) Log.d(TAG,关停);}公共无效setPainters(布尔翻转){ //初始化非像素图地区涂料 mEmptyPaint.setStyle(Paint.Style.FILL); mNoPagePaint.setStyle(Paint.Style.FILL); mStatusPaint.setStyle(Paint.Style.FILL); 如果(反转) mEmptyPaint.setColor(0xff000000); //黑色 其他 mEmptyPaint.setColor(0xffc0c0c0); // 浅灰 如果(反转) mNoPagePaint.setColor(0xff000000); //黑色 其他 mNoPagePaint.setColor(0xff303030); // 深灰色 如果(反转) mStatusPaint.setColor(0xff000000); //黑色 其他 mStatusPaint.setColor(0xff808080); //中灰}公共无效triggerRepaint(){ 如果(LOG) Log.d(TAG,重绘触发); 打断();}} 解决方案 我使用的这个,在我的情况下,其做工精细,下面是IMAGEFRAME 的FrameLayout ,我查看根视图,我要保存为位图。 位图saveBitmap = Bitmap.createBitmap(imageFrame.getWidth(),imageFrame.getHeight(),Bitmap.Config.ARGB_8888);帆布C =新的Canvas(saveBitmap);imageFrame.draw(C); 试着用您的视图替换IMAGEFRAME。 编辑: 日期日期=新的日期(); 文件filename =新的文件(file.getAbsoluteFile(),+ date.getTime()+.JPG); 尝试 { FOUT =新的FileOutputStream(文件名); saveBitmap.com preSS(Bitmap.Com pressFormat.JPEG,50,FOUT); 尝试 { fOut.flush(); fOut.close(); } 赶上(IOException异常E) { e.printStackTrace(); } } 赶上(FileNotFoundException异常E) { e.printStackTrace(); } 编辑2: 私人无效doDraw(){ INT W = WIDTH_PX,H = HEIGHT_PX; BitmapConfig的conf = Bitmap.Config.ARGB_8888; //看其他的conf类型 BMP位图= Bitmap.createBitmap(W,H,CONF); //这将创建一个可变的位图 C =新的Canvas(BMP); I had tried alot & even search alot but i didn't found the solution about the black screen which i get by fetching the cache view on the surface view..if is there any other way to capture the screen then let me know about this..if i use another control & fetching the drawable cache of that control it also return null..this is the code which i used to fetch the screen Image....try { // Button btn = new Button(mActivity.getApplicationContext()); view.buildDrawingCache(); view.setDrawingCacheEnabled(true); Bitmap b = view.getDrawingCache(); b.compress(CompressFormat.JPEG, 100, new FileOutputStream( "/mnt/sdcard/documents/" + new Date().getTime() + ".JPEG"));} catch (Exception e) { e.printStackTrace();}i had used this on the touch_up action of the surface view.....EDIT:public class DroidReaderActivity extends Activity {private static final boolean LOG = false;private static final int REQUEST_CODE_PICK_FILE = 1;private static final int REQUEST_CODE_OPTION_DIALOG = 2;private static final int DIALOG_GET_PASSWORD = 1;private static final int DIALOG_ABOUT = 2;private static final int DIALOG_GOTO_PAGE = 3;private static final int DIALOG_WELCOME = 4;private static final int DIALOG_ENTER_ZOOM = 5;private static final String PREFERENCE_EULA_ACCEPTED = "eula.accepted";private static final String PREFERENCES_EULA = "eula";protected DroidReaderView mReaderView = null;protected DroidReaderDocument mDocument = null;protected Menu m_ZoomMenu;FrameLayout fl;private String mFilename;private String mTemporaryFilename;private String mPassword;private int mPageNo;private SQLiteDatabase db;static DatabaseConnectionAPI db_api;private boolean mDocumentIsOpen = false;private boolean mLoadedDocument = false;private boolean mWelcomeShown = false;@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQUEST_CODE_PICK_FILE: if (resultCode == RESULT_OK && data != null) { // Theoretically there could be a case where OnCreate() is called // again with the intent that was originally used to open the app, // which would revert to a previous document. Use setIntent // to update the intent that will be supplied back to OnCreate(). setIntent(data); mTemporaryFilename = data.getDataString(); if (mTemporaryFilename != null) { if (mTemporaryFilename.startsWith("file://")) { mTemporaryFilename = mTemporaryFilename.substring(7); } mPassword = ""; openDocumentWithDecodeAndLookup(); } } break; case REQUEST_CODE_OPTION_DIALOG: readPreferences(); tryLoadLastFile(); break; }}/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); System.out.println("ONCREATE"); db_api = new DatabaseConnectionAPI(this); try { db_api.createDataBase(); db_api.openDataBase(); } catch (IOException e) { e.printStackTrace(); } // first, show the welcome if it hasn't been shown already: final SharedPreferences preferences = getSharedPreferences(PREFERENCES_EULA, Context.MODE_PRIVATE); if (!preferences.getBoolean(PREFERENCE_EULA_ACCEPTED, false)) { mWelcomeShown = true; preferences.edit().putBoolean(PREFERENCE_EULA_ACCEPTED, true).commit(); showDialog(DIALOG_WELCOME); } if (mDocument == null) mDocument = new DroidReaderDocument(); // Initialize the PdfRender engine PdfRender.setFontProvider(new DroidReaderFontProvider(this)); // then build our layout. it's so simple that we don't use // XML for now. fl = new FrameLayout(this); mReaderView = new DroidReaderView(this, null, mDocument); // add the viewing area and the navigation fl.addView(mReaderView); setContentView(fl); readPreferences(); if (savedInstanceState != null) { mFilename = savedInstanceState.getString("filename"); if ((new File(mFilename)).exists()) { mPassword = savedInstanceState.getString("password"); mDocument.mZoom = savedInstanceState.getFloat("zoom"); mDocument.mRotation = savedInstanceState.getInt("rotation"); mPageNo = savedInstanceState.getInt("page"); mDocument.mMarginOffsetX = savedInstanceState.getInt("marginOffsetX"); mDocument.mMarginOffsetY = savedInstanceState.getInt("marginOffsetY"); mDocument.mContentFitMode = savedInstanceState.getInt("contentFitMode"); openDocument(); mLoadedDocument = true; } savedInstanceState.clear(); } Timer mTimer = new Timer(); mTimer.schedule(new TimerTask() { @Override public void run() { try { Bitmap saveBitmap = Bitmap.createBitmap(fl.getWidth(), fl.getHeight(), Bitmap.Config.ARGB_8888); saveBitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream("/mnt/sdcard/documents/" + new Date().getTime() + ".JPEG")); } catch (Exception e) { e.printStackTrace(); } } }, 4000); }}@Overrideprotected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if ((mDocument != null) && mDocument.isPageLoaded()) { outState.putFloat("zoom", mDocument.mZoom); outState.putInt("rotation", mDocument.mRotation); outState.putInt("page", mDocument.mPage.no); outState.putInt("offsetX", mDocument.mOffsetX); outState.putInt("offsetY", mDocument.mOffsetY); outState.putInt("marginOffsetX", mDocument.mMarginOffsetX); outState.putInt("marginOffsetY", mDocument.mMarginOffsetY); outState.putInt("contentFitMode", mDocument.mContentFitMode); outState.putString("password", mPassword); outState.putString("filename", mFilename); mDocument.closeDocument(); }}public void onTap(float X, float Y) { float left, right, top, bottom; float width = mDocument.mDisplaySizeX; float height = mDocument.mDisplaySizeY; boolean prev = false; boolean next = false; if (mDocumentIsOpen) { left = width * (float) 0.25; right = width * (float) 0.75; top = height * (float) 0.25; bottom = height * (float) 0.75; if ((X < left) && (Y < top)) prev = true; if ((X < left) && (Y > bottom)) next = true; if ((X > right) && (Y < top)) prev = true; if ((X > right) && (Y > bottom)) next = true; if ((X > left) && (X < right) && (Y > bottom)) { Log.d("DroidReaderMetrics", String.format("Zoom = %5.2f%%", mDocument.mZoom * 100.0)); Log.d("DroidReaderMetrics", String.format("Page size = (%2.0f,%2.0f)", mDocument.mPage.mMediabox[2] - mDocument.mPage.mMediabox[0], mDocument.mPage.mMediabox[3] - mDocument.mPage.mMediabox[1])); Log.d("DroidReaderMetrics", String.format( "Display size = (%d,%d)", mDocument.mDisplaySizeX, mDocument.mDisplaySizeY)); Log.d("DroidReaderMetrics", String.format("DPI = (%d, %d)", mDocument.mDpiX, mDocument.mDpiY)); Log.d("DroidReaderMetrics", String.format("Content size = (%2.0f,%2.0f)", mDocument.mPage.mContentbox[2] - mDocument.mPage.mContentbox[0], mDocument.mPage.mContentbox[3] - mDocument.mPage.mContentbox[1])); Log.d("DroidReaderMetrics", String.format("Content offset = (%2.0f,%2.0f)", mDocument.mPage.mContentbox[0], mDocument.mPage.mContentbox[1])); Log.d("DroidReaderMetrics", String.format( "Document offset = (%d,%d)", mDocument.mOffsetX, mDocument.mOffsetY)); } if (next) { if (mDocument.havePage(1, true)) openPage(1, true); } else if (prev) { if (mDocument.havePage(-1, true)) openPage(-1, true); } }}protected void openDocument() { // Store the view details for the previous document and close it. if (mDocumentIsOpen) { mDocument.closeDocument(); mDocumentIsOpen = false; } try { this.setTitle(mFilename); mDocument.open(mFilename, mPassword, mPageNo); openPage(0, true); mDocumentIsOpen = true; } catch (PasswordNeededException e) { showDialog(DIALOG_GET_PASSWORD); } catch (WrongPasswordException e) { Toast.makeText(this, R.string.error_wrong_password, Toast.LENGTH_LONG).show(); } catch (Exception e) { Toast.makeText(this, R.string.error_opening_document, Toast.LENGTH_LONG).show(); }}protected void openDocumentWithDecodeAndLookup() { try { mTemporaryFilename = URLDecoder.decode(mTemporaryFilename, "utf-8"); // Do some sanity checks on the supplied filename. File f = new File(mTemporaryFilename); if ((f.exists()) && (f.isFile()) && (f.canRead())) { mFilename = mTemporaryFilename; openDocumentWithLookup(); } else { Toast.makeText(this, R.string.error_file_open_failed, Toast.LENGTH_LONG).show(); } } catch (Exception e) { Toast.makeText(this, R.string.error_opening_document, Toast.LENGTH_LONG).show(); }}protected void openDocumentWithLookup() { readOrWriteDB(false); openDocument();}protected void openPage(int no, boolean isRelative) { try { if (!(no == 0 && isRelative)) mDocument.openPage(no, isRelative); this.setTitle(new File(mFilename).getName() + String.format(" (%d/%d)", mDocument.mPage.no, mDocument.mDocument.pagecount)); mPageNo = mDocument.mPage.no; } catch (PageLoadException e) { }}private void readPreferences() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); if (prefs.getString("zoom_type", "0").equals("0")) { float zoom = Float.parseFloat(prefs.getString("zoom_percent", "50")); if ((1 <= zoom) && (1000 >= zoom)) { mDocument.setZoom(zoom / 100, false); } } else { mDocument.setZoom(Float.parseFloat(prefs.getString("zoom_type", "0")), false); } if (prefs.getBoolean("dpi_auto", true)) { // read the display's DPI mDocument.setDpi((int) metrics.xdpi, (int) metrics.ydpi); } else { int dpi = Integer.parseInt(prefs.getString("dpi_manual", "160")); if ((dpi < 1) || (dpi > 4096)) dpi = 160; // sanity check fallback mDocument.setDpi(dpi, dpi); } if (prefs.getBoolean("tilesize_by_factor", true)) { // set the tile size for rendering by factor Float factor = Float.parseFloat(prefs.getString("tilesize_factor", "1.5")); mDocument.setTileMax((int) (metrics.widthPixels * factor), (int) (metrics.heightPixels * factor)); } else { int tilesize_x = Integer.parseInt(prefs.getString("tilesize_x", "640")); int tilesize_y = Integer.parseInt(prefs.getString("tilesize_x", "480")); if (metrics.widthPixels < metrics.heightPixels) { mDocument.setTileMax(tilesize_x, tilesize_y); } else { mDocument.setTileMax(tilesize_y, tilesize_x); } } boolean invert = prefs.getBoolean("invert_display", false); mDocument.setDisplayInvert(invert); mReaderView.setDisplayInvert(invert); if (prefs.getBoolean("full_screen", false)) { this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } else { this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } mDocument.mHorizontalScrollLock = prefs.getBoolean("horizontal_scroll_lock", false);}protected void setZoom(float newZoom) { newZoom = newZoom / (float) 100.0; if (newZoom > 16.0) newZoom = (float) 16.0; if (newZoom < 0.0625) newZoom = (float) 0.0625; mDocument.setZoom(newZoom, false);}protected void tryLoadLastFile() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); mFilename = prefs.getString("last_open_file", ""); if (mFilename != null) { if ((mFilename.length() > 0) && ((new File(mFilename)).exists())) { // Don't URL-decode the filename, as that's presumably already been done. mPassword = ""; openDocumentWithLookup(); mLoadedDocument = true; } }}}DroidReaderView:public class DroidReaderView extends SurfaceView implements OnGestureListener, SurfaceHolder.Callback, DroidReaderDocument.RenderListener {public static Path mPath = new Path();private static StringBuffer sbx = new StringBuffer();private static StringBuffer sby = new StringBuffer();public static Paint mPaint = new Paint();public static Paint nullpaint = new Paint();private String sx, sy, sbx_str, sby_str;public static Canvas mCanvas = new Canvas();private int pid = 1;/** * Debug helper */protected final static String TAG = "DroidReaderView";protected final static boolean LOG = false;/** * our view thread which does the drawing */public DroidReaderViewThread mThread;/** * our gesture detector */protected final GestureDetector mGestureDetector;/** * our context */protected final DroidReaderActivity mActivity;/** * our SurfaceHolder */protected final SurfaceHolder mSurfaceHolder;public static DroidReaderDocument mDocument;protected boolean mDisplayInvert;/** * constructs a new View * * @param context * Context for the View * @param attrs * attributes (may be null) */public DroidReaderView(final DroidReaderActivity activity, AttributeSet attrs, DroidReaderDocument document) { super(activity, attrs); mActivity = activity; mSurfaceHolder = getHolder(); mDocument = document; mDocument.mRenderListener = this; mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(12); // tell the SurfaceHolder to inform this thread on // changes to the surface mSurfaceHolder.addCallback(this); mGestureDetector = new GestureDetector(this);}/* event listeners: */@Overrideprotected void onDraw(Canvas canvas) { mThread.c = canvas; mThread.c = mSurfaceHolder.lockCanvas(); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setColor(Color.RED); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(12); mThread.c.drawPath(mPath, mPaint); mSurfaceHolder.unlockCanvasAndPost(mThread.c);}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (LOG) Log.d(TAG, "onFling(): notifying ViewThread"); mThread.mScroller.fling(0, 0, -(int) velocityX, -(int) velocityY, -4096, 4096, -4096, 4096); mThread.triggerRepaint(); return true;}/* keyboard events: */@Overridepublic boolean onKeyDown(int keyCode, KeyEvent msg) { if (LOG) Log.d(TAG, "onKeyDown(), keycode " + keyCode); return false;}@Overridepublic boolean onKeyUp(int keyCode, KeyEvent msg) { if (LOG) Log.d(TAG, "onKeyUp(), keycode " + keyCode); return false;}/* interface for the GestureListener: */@Overridepublic void onLongPress(MotionEvent e) { if (LOG) Log.d(TAG, "onLongPress(): ignoring!");}@Overridepublic void onNewRenderedPixmap() { if (LOG) Log.d(TAG, "new rendered pixmap was signalled"); mThread.triggerRepaint();}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (LOG) Log.d(TAG, "onScroll(), distance vector: " + distanceX + "," + distanceY); mDocument.offset((int) distanceX, (int) distanceY, true); mThread.triggerRepaint(); return true;}@Overridepublic void onShowPress(MotionEvent e) { if (LOG) Log.d(TAG, "onShowPress(): ignoring!");}@Overridepublic boolean onSingleTapUp(MotionEvent e) { // Pass the tap, and the window dimensions, to the activity to process. mActivity.onTap(e.getX(), e.getY()); return true;}private float mX, mY;private static final float TOUCH_TOLERANCE = 4;private void touch_start(float x, float y) { mPath.moveTo(x, y); mX = x; sx = Float.toString(mX); sbx.append(sx); sbx.append(","); mY = y; sy = Float.toString(mY); sby.append(sy); sby.append(","); sbx_str = sbx.toString(); sby_str = sby.toString();}private void draw_move(float x, float y) { float dx = Math.abs(x - mX); float dy = Math.abs(y - mY); if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2); mX = x; sx = Float.toString(mX); sbx.append(sx); sbx.append(","); mY = y; sy = Float.toString(mY); sby.append(sy); sby.append(","); }}private void touch_up() { mPath.lineTo(mX, mY); sx = Float.toString(mX); sbx.append(sx); sbx.append(","); sy = Float.toString(mY); sby.append(sy); sby.append(","); mPath.reset(); sbx_str = sbx.toString().trim(); sby_str = sby.toString().trim(); insert(TAGS.presentation_id, mDocument.mPage.no, sbx_str, sby_str); sbx = new StringBuffer(); sby = new StringBuffer(); System.out.println(sbx_str.trim()); System.out.println(sby_str.trim());}@Overridepublic boolean onTouchEvent(final MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: touch_start(x, y); invalidate(); break; case MotionEvent.ACTION_MOVE: draw_move(x, y); invalidate(); break; case MotionEvent.ACTION_UP: touch_up(); invalidate(); try { // Button btn = new Button(mActivity.getApplicationContext()); // buildDrawingCache(); // setDrawingCacheEnabled(true); // Bitmap b = getDrawingCache(); // b.compress(CompressFormat.JPEG, 100, new FileOutputStream( // "/mnt/sdcard/documents/" + new Date().getTime() + ".JPEG")); } catch (Exception e) { e.printStackTrace(); } break; } invalidate(); if (LOG) { Log.d(TAG, "onTouchEvent(): notifying mGestureDetector"); invalidate(); } if (mGestureDetector.onTouchEvent(event)) { invalidate(); return true; } return true;}@Overridepublic boolean onTrackballEvent(MotionEvent event) { if (LOG) Log.d(TAG, "onTouchEvent(): notifying ViewThread"); mDocument .offset((int) event.getX() * 20, (int) event.getY() * 20, true); mThread.triggerRepaint(); return true;}/* surface events: */public void setDisplayInvert(boolean invert) { if (mThread != null) mThread.setPainters(invert); mDisplayInvert = invert;}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (LOG) Log.d(TAG, "surfaceChanged(): size " + width + "x" + height); mDocument.startRendering(width, height);}@Overridepublic void surfaceCreated(SurfaceHolder holder) { if (LOG) Log.d(TAG, "surfaceCreated(): starting ViewThread"); mThread = new DroidReaderViewThread(holder, mActivity, mDocument); mThread.setPainters(mDisplayInvert); mThread.start();}/* render events */@Overridepublic void surfaceDestroyed(SurfaceHolder holder) { if (LOG) Log.d(TAG, "surfaceDestroyed(): dying"); mDocument.stopRendering(); boolean retry = true; mThread.mRun = false; mThread.interrupt(); while (retry) { try { mThread.join(); retry = false; } catch (InterruptedException e) { } }}@Overridepublic boolean onDown(MotionEvent e) { return false;}DroidReaderViewThread :Thread that cares for blitting Pixmaps onto the Canvas and handles scrollingclass DroidReaderViewThread extends Thread {public Canvas c = new Canvas();private Cursor mCursor;private Path mPath1 = new Path();private StringBuffer sbx_read, sby_read;public static Paint mPaint2 = new Paint();public static Paint mPaint3 = new Paint();Path old_path = new Path();/** * Debug helper */protected final static String TAG = "DroidReaderViewThread";protected final static boolean LOG = false;/** * the SurfaceHolder for our Surface */protected final SurfaceHolder mSurfaceHolder;/** * Paint for not (yet) rendered parts of the page */protected final Paint mEmptyPaint;/** * Paint for filling the display when there is no PdfPage (yet) */protected final Paint mNoPagePaint;/** * Paint for the status text */protected final Paint mStatusPaint;/** * Flag that our thread should be running */protected boolean mRun = true;/** * our scroller */protected final Scroller mScroller;protected final DroidReaderDocument mDocument;/** * Background render thread, using the SurfaceView programming scheme * * @param holder * our SurfaceHolder * @param context * the Context for our drawing */public DroidReaderViewThread(SurfaceHolder holder, Context context, DroidReaderDocument document) { // store a reference to our SurfaceHolder mSurfaceHolder = holder; mDocument = document; // initialize Paints for non-Pixmap areas mEmptyPaint = new Paint(); mNoPagePaint = new Paint(); mStatusPaint = new Paint(); setPainters(false); // the scroller, i.e. the object that calculates/interpolates // positions for scrolling/jumping/flinging mScroller = new Scroller(context);}/** * ll this does the actual drawing to the Canvas for our surface */private void doDraw() { if (LOG) Log.d(TAG, "drawing..."); c = null; try { c = mSurfaceHolder.lockCanvas(null); if (!mDocument.isPageLoaded()) { // no page/document loaded if (LOG) Log.d(TAG, "no page loaded."); c.drawRect(0, 0, c.getWidth(), c.getHeight(), mNoPagePaint); } else if (mDocument.havePixmap()) { // we have both page and Pixmap, so draw: // background: if (LOG) Log.d(TAG, "page loaded, rendering pixmap"); c.drawRect(0, 0, c.getWidth(), c.getHeight(), mEmptyPaint); Log.d("CALL", "CALL"); c.drawBitmap(mDocument.mView.mBuf, 0, mDocument.mView.mViewBox.width(), -mDocument.mOffsetX + mDocument.mView.mViewBox.left, -mDocument.mOffsetY + mDocument.mView.mViewBox.top, mDocument.mView.mViewBox.width(), mDocument.mView.mViewBox.height(), false, null); try { Log.d("Reading", "Reading"); mCursor = DroidReaderActivity.db_api .ExecuteQueryGetCursor("SELECT * FROM path WHERE page_no=" + mDocument.mPage.no + " AND presentation_id=" + TAGS.presentation_id + ";"); if (!mCursor.equals(null)) { mCursor.moveToFirst(); float x1 = 0, y1 = 0; int pid = 0; do { sbx_read = new StringBuffer(); sbx_read.append(mCursor.getString(mCursor.getColumnIndex("x_path"))); sby_read = new StringBuffer(); sby_read.append(mCursor.getString(mCursor.getColumnIndex("y_path"))); String[] sbx_read_array = sbx_read.toString().trim().split(","); String[] sby_read_array = sby_read.toString().trim().split(","); for (int i = 0; i < sbx_read_array.length; i++) { x1 = Float.parseFloat(sbx_read_array[i].toString()); y1 = Float.parseFloat(sby_read_array[i].toString()); if (pid != mCursor.getInt(mCursor.getColumnIndex("path_id"))) { pid = mCursor.getInt(mCursor.getColumnIndex("path_id")); Log.d("New Path Id.", String.valueOf(mCursor.getInt(mCursor.getColumnIndex("path_id")))); mPath1.reset(); mPath1.moveTo(x1, y1); } else { Log.d("Path id repeating.", String.valueOf(mCursor.getInt(mCursor.getColumnIndex("path_id")))); } mPath1.lineTo(x1, y1); c.drawPath(mPath1, DroidReaderView.mPaint); } } while (mCursor.moveToNext()); mCursor.close(); Log.d("Read mode Complete", "Read mode Complete"); } } catch (Exception e) { // Log.d("read Cursor", e.getMessage().toString()); } } else { // page loaded, but no Pixmap yet if (LOG) Log.d(TAG, "page loaded, but no active Pixmap."); c.drawRect(0, 0, c.getWidth(), c.getHeight(), mEmptyPaint); mPaint3.setAntiAlias(true); mPaint3.setDither(true); mPaint3.setColor(Color.TRANSPARENT); mPaint3.setStyle(Paint.Style.STROKE); mPaint3.setStrokeJoin(Paint.Join.ROUND); mPaint3.setStrokeCap(Paint.Cap.ROUND); mPaint3.setStrokeWidth(12); mPaint3.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); c.drawPath(old_path, mPaint3); } } finally { if (c != null) { mPaint2.setAntiAlias(true); mPaint2.setDither(true); mPaint2.setColor(Color.GREEN); mPaint2.setStyle(Paint.Style.STROKE); mPaint2.setStrokeJoin(Paint.Join.ROUND); mPaint2.setStrokeCap(Paint.Cap.ROUND); mPaint2.setStrokeWidth(12); c.drawPath(DroidReaderView.mPath, mPaint2); // DroidReaderView.mPath.reset(); // old_path = DroidReaderView.mPath; } mSurfaceHolder.unlockCanvasAndPost(c); }}/** * Main Thread loop */@SuppressWarnings("static-access")@Overridepublic void run() { while (mRun) { boolean doSleep = true; if (!mScroller.isFinished()) { if (mScroller.computeScrollOffset()) { if (LOG) Log.d(TAG, "new scroll offset"); doSleep = false; int oldX = mDocument.mOffsetX; int oldY = mDocument.mOffsetY; mDocument.offset(mScroller.getCurrX(), mScroller.getCurrY(), true); if ((oldX == mDocument.mOffsetX) && (oldY == mDocument.mOffsetY)) mScroller.abortAnimation(); } else { mScroller.abortAnimation(); } } doDraw(); // if we're allowed, we will go to sleep now if (doSleep) { try { // nothing to do, wait for someone waking us up: if (LOG) Log.d(TAG, "ViewThread going to sleep"); // between // the check for pending interrupts and the sleep() which // could lead to a not-handled repaint request: if (!this.interrupted()) Thread.sleep(3600000); } catch (InterruptedException e) { if (LOG) Log.d(TAG, "ViewThread woken up"); } } } // mRun is now false, so we shut down. if (LOG) Log.d(TAG, "shutting down");}public void setPainters(boolean invert) { // initialize Paints for non-Pixmap areas mEmptyPaint.setStyle(Paint.Style.FILL); mNoPagePaint.setStyle(Paint.Style.FILL); mStatusPaint.setStyle(Paint.Style.FILL); if (invert) mEmptyPaint.setColor(0xff000000); // black else mEmptyPaint.setColor(0xffc0c0c0); // light gray if (invert) mNoPagePaint.setColor(0xff000000); // black else mNoPagePaint.setColor(0xff303030); // dark gray if (invert) mStatusPaint.setColor(0xff000000); // black else mStatusPaint.setColor(0xff808080); // medium gray}public void triggerRepaint() { if (LOG) Log.d(TAG, "repaint triggered"); interrupt();}} 解决方案 I am using this, and its works fine in my case,Here imageFrame is FrameLayout, root view of my View which I want to save as bitmap..Bitmap saveBitmap = Bitmap.createBitmap(imageFrame.getWidth(), imageFrame.getHeight(), Bitmap.Config.ARGB_8888);Canvas c = new Canvas(saveBitmap);imageFrame.draw(c);Try replacing imageFrame with your view.EDIT: Date date = new Date(); File filename = new File(file.getAbsoluteFile(), "" + date.getTime() + ".jpg"); try { fOut = new FileOutputStream(filename); saveBitmap.compress(Bitmap.CompressFormat.JPEG, 50, fOut); try { fOut.flush(); fOut.close(); } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); }EDIT 2:private void doDraw() { int w = WIDTH_PX, h = HEIGHT_PX; BitmapConfig conf = Bitmap.Config.ARGB_8888; // see other conf types Bitmap bmp = Bitmap.createBitmap(w, h, conf); // this creates a MUTABLE bitmap c = new Canvas(bmp); 这篇关于SurfaceView返回droidreader黑色屏幕的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!