如何使用isInEditMode(),看看在编辑器中使用自定义视图布局 [英] How to use isInEditMode() to see layout with custom View in the editor
本文介绍了如何使用isInEditMode(),看看在编辑器中使用自定义视图布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我必须编辑有一个自定义视图,当我尝试编辑布局XML软件,Eclipse的说我:
使用View.isInEditMode()在你的自定义视图跳过code时,显示 在Eclipse
但我不知道有关的如何和其中的我必须使用的 isInEditMode()的应用程序中的
我的XML文件是
< XML版本=1.0编码=UTF-8&GT?;
<的LinearLayout
的xmlns:机器人=http://schemas.android.com/apk/res/android
机器人:方向=垂直
机器人:layout_width =FILL_PARENT
机器人:layout_height =FILL_PARENT
机器人:后台=#FF000000
>
<的TextView
机器人:ID =@ + ID /结果
机器人:layout_width =FILL_PARENT
机器人:layout_height =WRAP_CONTENT
机器人:重力=右
机器人:TEXTSIZE =32dip
机器人:滚动条=无
机器人:行=1
机器人:freezesText =真
机器人:文字颜色=@色/结果
/>
<的EditText
机器人:ID =@ + ID /输入
机器人:layout_width =FILL_PARENT
机器人:layout_height =WRAP_CONTENT
机器人:重力=左
机器人:TEXTSIZE =28DIP
机器人:滚动条=无
机器人:单线=真
机器人:自动图文集=假
机器人:imeOptions =flagNoEnterAction | flagNoExtractUi
/>
<的ListView
机器人:ID =@ + ID /史
机器人:layout_width =FILL_PARENT
机器人:layout_height =0dip
机器人:layout_weight =1
机器人:cacheColorHint =#FF000000
机器人:choiceMode =singleChoice
机器人:scrollbarStyle =outsideInset
机器人:滚动条=无
/>
< calculator.GraphView
机器人:ID =@ + ID /图
机器人:layout_width =FILL_PARENT
机器人:layout_height =0dip
机器人:layout_weight =1
机器人:能见度=水涨船高
/>
<包括布局=@布局/键盘/>
< / LinearLayout中>
和我GraphView是
公共类GraphView扩展视图实现绘图,
ZoomButtonsController.OnZoomListener,
TouchHandler.TouchHandlerInterface {
私人诠释的宽度,高度;
私人矩阵的矩阵=新的Matrix();
民营涂料粉刷=新的油漆();
民营涂料textPaint =新的油漆();
私人的ArrayList<作用> funcs中=新的ArrayList<作用>();
私人数据下一=新的Data(),endGraph =新的Data();
私人数据图[] = {新的Data(),新的Data(),新的Data(),新的Data()
新的Data()};
私有静态最终诠释GRAPHS_SIZE = 5;
私人浮动gwidth = 8;
私人浮动currentX,currentY;
私人浮动lastMinX;
私人滚轮滚动;
私人浮动boundMinY,boundMaxY;
保护ZoomButtonsController zoomController =新ZoomButtonsController(
本);
私人ZoomTracker zoomTracker =新ZoomTracker();
私人TouchHandler touchHandler;
私人浮动lastTouchX,lastTouchY;
私有静态最终诠释COL_AXIS = 0xff00a000,COL_GRID = 0xff004000,
COL_TEXT = 0xff00ff00;
私有静态最终诠释COL_GRAPH [] = {为0xffffffff,0xff00ffff,
0xffffff00,0xffff00ff,0xff80ff80};
公共GraphView(上下文的背景下,ATTRS的AttributeSet){
超(背景下,ATTRS);
的init(上下文);
}
公共GraphView(上下文的背景下){
超(上下文);
touchHandler =新TouchHandler(本);
的init(上下文);
}
私人无效的init(上下文的背景下){
zoomController.setOnZoomListener(本);
滚动=新的滚轮(上下文);
paint.setAntiAlias(假);
textPaint.setAntiAlias(真正的);
}
@燮pressLint(WrongCall)
公共字符串captureScreenshot(){
点阵位图= Bitmap.createBitmap(宽度,高度,
Bitmap.Config.RGB_565);
帆布油画=新的Canvas(位);
的OnDraw(画布);
返回Util.saveBitmap(位图,Grapher.SCREENSHOT_DIR,计算器);
}
私人无效clearAllGraph(){
的for(int i = 0; I< GRAPHS_SIZE ++我){
图[我] .clear();
}
}
公共无效setFunctions(ArrayList的<作用> FS){
funcs.clear();
对于(功能F:FS){
INT元数= f.arity();
如果(参数数量== 0 ||元数== 1){
funcs.add(F);
}
}
clearAllGraph();
无效();
}
公共无效setFunction(功能F){
funcs.clear();
如果(F!= NULL){
funcs.add(F);
}
clearAllGraph();
无效();
}
公共无效onVisibilityChanged(布尔可见){
}
公共无效onZoom(布尔zoomIn){
如果(zoomIn){
如果(canZoomIn()){
gwidth / = 2;
invalidateGraphs();
}
} 其他 {
如果(canZoomOut()){
gwidth * = 2;
invalidateGraphs();
}
}
zoomController.setZoomInEnabled(canZoomIn());
zoomController.setZoomOutEnabled(canZoomOut());
}
公共无效onResume(){
}
公共无效的onPause(){
}
公共无效onDetachedFromWindow(){
zoomController.setVisible(假);
super.onDetachedFromWindow();
}
保护无效onSizeChanged(INT W,INT小时,INT流,诠释哦){
宽= W;
高度= H;
clearAllGraph();
}
保护无效的OnDraw(帆布油画){
如果(funcs.size()== 0){
返回;
}
如果(scroller.computeScrollOffset()){
最终浮动规模= gwidth /宽;
currentX = scroller.getCurrX()*规模;
currentY = scroller.getCurrY()*规模;
如果(!scroller.isFinished()){
无效();
}
}
drawGraph(画布);
}
私人浮动的eval(功能楼浮动X){
浮动V =(浮点)f.eval(X);
如果(V族; -10000f){
返回-10000f;
}
如果(V> 1000°F){
返回10000F;
}
返回伏;
}
私人浮动距离2(浮动X1,Y1浮球,浮球X2,Y2浮球,浮球Y){
最终浮动DX = X2 - X1;
最终浮动DY = Y2 - Y1;
最终浮动起来= DX *(Y1 + Y2 - Y - Y);
返回最多*升/(DX * DX + DY * DY);
}
私人无效computeGraph(功能楼飘了minX,浮MAXX,浮MINY,
浮MAXY,数据图表){
如果(f.arity()== 0){
浮动V =(浮点)f.eval();
如果(V族; -10000f){
V = -10000f;
}
如果(V> 1000°F){
V = 10000F;
}
graph.clear();
graph.push(其minX,V);
graph.push(MAXX,V);
返回;
}
最终浮动规模=宽/ gwidth;
最终浮动maxStep = 15.8976f /规模;
最终浮动minStep = .05f /规模;
浮ythresh = 1 /规模;
ythresh = ythresh * ythresh;
如果(!graph.empty()){
如果(其minX> = lastMinX){
graph.eraseBefore(其minX);
} 其他 {
graph.eraseAfter(MAXX);
MAXX = Math.min(MAXX,graph.firstX());
graph.swap(endGraph);
}
}
如果(graph.empty()){
graph.push(其minX中,eval(F,其minX));
}
浮leftX,左撇子;
浮rightX = graph.topX(),用右手= graph.topY();
INT nEval = 1;
而(真){
leftX = rightX;
左撇子=右倾;
如果(leftX> MAXX){
打破;
}
如果(next.empty()){
浮动X = leftX + maxStep;
next.push(X中,eval(F,X));
++ nEval;
}
rightX = next.topX();
右倾= next.topY();
next.pop();
如果(左撇子=左手和放大器;!&安培;!用右手=用右手){//为NaN
继续;
}
浮DX = rightX - leftX;
浮middleX =(leftX + rightX)/ 2;
浮middleY =的eval(F,middleX);
++ nEval;
布尔middleIsOutside =(middleY<左撇子和放大器;&安培; middleY<用右手)
|| (左撇子< middleY和放大器;&安培;右倾< middleY);
如果(DX< minStep){
如果(middleIsOutside){
graph.push(rightX,的Float.NaN);
}
graph.push(rightX,用右手);
继续;
}
如果(middleIsOutside
&功放;&安培; ((左撇子< MINY和放大器;&安培;右倾> MAXY)||(左撇子> MAXY和放大器;&安培;右倾< MINY))){
graph.push(rightX,的Float.NaN);
graph.push(rightX,用右手);
继续;
}
如果(!middleIsOutside){
如果(距离2(leftX,左撇子,rightX,用右手,middleY)< ythresh){
graph.push(rightX,用右手);
继续;
}
}
next.push(rightX,用右手);
next.push(middleX,middleY);
rightX = leftX;
用右手=左撇子;
}
如果(!endGraph.empty()){
graph.append(endGraph);
}
长T2 = System.currentTimeMillis的();
next.clear();
endGraph.clear();
}
私有静态路径path =新路径();
私人路径graphToPath(资料图){
布尔第一= TRUE;
INT大小= graph.size;
浮动[] XS = graph.xs;
浮动[] YS = graph.ys;
path.rewind();
的for(int i = 0; I<大小; ++ I){
浮动Y = YS [I]
浮法X = XS [I]
// Calculator.log(路径+ X +''+ Y);
如果(Y == Y){//!NaN的
如果(第一){
path.moveTo(X,Y);
第一= FALSE;
} 其他 {
path.lineTo(X,Y);
}
} 其他 {
第一= TRUE;
}
}
返回路径;
}
私有静态最终浮动NTICKS = 15;
私有静态浮动stepFactor(浮点W){
浮动F = 1;
而(W / F> NTICKS){
F * = 10;
}
而(W / F< NTICKS / 10){
的f / = 10;
}
浮动R = W / F;
如果(R< NTICKS / 5){
返回F / 5;
}否则,如果(R< NTICKS / 2){
返回的f / 2;
} 其他 {
返回F;
}
}
私有静态StringBuilder的B =新的StringBuilder();
私有静态的char [] buf中=新的字符[20];
私有静态StringBuilder的格式(浮点FV){
INT POS = 0;
布尔addDot = FALSE;
INT V = Math.round(FV * 100);
布尔isNeg = V< 0;
V = isNeg? -v:伏;
对(INT I = 0; I&2 ++ⅰ){
INT位= v%的10;
体积/ = 10;
如果(数字!= 0 || addDot){
BUF [POS +] =(char)的('0'+数字);
addDot =真;
}
}
如果(addDot){
BUF [POS +] ='';
}
如果(V == 0){
BUF [POS +] ='0';
}
而(ⅴ!= 0){
的buf [POS ++] =(char)的('0'+(v%的10));
体积/ = 10;
}
如果(isNeg){
的buf [POS ++] =' - ';
}
b.setLength(0);
在b.append(BUF,0,POS);
b.reverse();
返回b;
}
私人无效drawGraph(帆布油画){
长T1 = System.currentTimeMillis的();
漂浮其minX = currentX - gwidth / 2;
浮MAXX =其minX + gwidth;
浮ywidth = gwidth *高度/宽度;
浮MINY = currentY - ywidth / 2;
浮MAXY = MINY + ywidth;
如果(MINY< boundMinY || MAXY> boundMaxY){
浮halfw = ywidth / 2;
boundMinY = MINY - halfw;
boundMaxY = MAXY + halfw;
clearAllGraph();
}
canvas.drawColor(0xff000000);
paint.setStrokeWidth(0);
paint.setAntiAlias(假);
paint.setStyle(Paint.Style.STROKE);
最终浮动H2 =高度/ 2F;
最终浮动规模=宽/ gwidth;
浮X0 = -minX *规模;
布尔drawYAxis = TRUE;
如果(X0α25){
X0 = 25;
// drawYAxis = FALSE;
}否则如果(X0>宽度 - 3){
X0 =宽度 - 3;
// drawYAxis = FALSE;
}
浮Y0 = MAXY *规模;
如果(Y0 3;){
Y0 = 3;
}否则如果(Y0>高度 - 15){
Y0 =身高 - 15;
}
最终浮动tickSize = 3;
最终浮动Y2 = Y0 + tickSize;
paint.setColor(COL_GRID);
浮步= stepFactor(gwidth);
浮动V =((INT)(其minX /步))*步骤;
textPaint.setColor(COL_TEXT);
textPaint.setTextSize(12);
textPaint.setTextAlign(Paint.Align.CENTER);
浮stepScale =步*规模;
为(浮动X =(V - 其minX)*规模,X< =宽度; X + = stepScale,V + =步){
canvas.drawLine(X,0中,x,高度,漆);
如果(( - 001F<!V&功放;&安培; V< .001f)){
StringBuilder的B =格式(五);
canvas.drawText(二,0,b.length个()中,x,Y2 + 10,textPaint);
}
}
最终浮动X1 = X0 - tickSize;
V =((int)的(MINY /步骤))*步骤;
textPaint.setTextAlign(Paint.Align.RIGHT);
为(浮动Y =高度 - (五 - MINY)*标y与其所连接; = 0; Y - = stepScale,V + =步骤){
canvas.drawLine(0,Y,宽度,Y,油漆);
如果(( - 001F<!V&功放;&安培; V< .001f)){
StringBuilder的B =格式(五);
canvas.drawText(B,0,b.length个(),X1,Y + 4,textPaint);
}
}
paint.setColor(COL_AXIS);
如果(drawYAxis){
canvas.drawLine(X0,0,X0,高度,油漆);
}
canvas.drawLine(0,Y0,宽度,Y0,漆);
matrix.reset();
。矩阵preTranslate(-currentX,-currentY);
matrix.postScale(规模,-scale);
matrix.postTranslate(宽度/ 2,高度/ 2);
paint.setStrokeWidth(0);
paint.setAntiAlias(假);
INT N = Math.min(funcs.size(),GRAPHS_SIZE);
的for(int i = 0;我n种; ++ I){
computeGraph(funcs.get(ⅰ),其minX,MAXX,boundMinY,boundMaxY,
图表[I]);
路径path = graphToPath(图[I]);
path.transform(矩阵);
paint.setColor(COL_GRAPH [I]);
canvas.drawPath(路径,油漆);
}
lastMinX =其minX;
}
私人布尔canZoomIn(){
返回gwidth> 1F;
}
私人布尔canZoomOut(){
返回gwidth< 50;
}
私人无效invalidateGraphs(){
clearAllGraph();
boundMinY = boundMaxY = 0;
无效();
}
@覆盖
公共布尔的onTouchEvent(MotionEvent事件){
返回touchHandler!= NULL? touchHandler.onTouchEvent(事件):超
.onTouchEvent(事件);
}
公共无效onTouchDown(浮X,浮动Y){
zoomController.setVisible(真正的);
如果(!scroller.isFinished()){
scroller.abortAnimation();
}
lastTouchX = X;
lastTouchY = Y;
}
公共无效onTouchMove(浮X,浮动Y){
浮DELTAX = X - lastTouchX;
漂浮移动deltaY = Y - lastTouchY;
如果(DELTAX&所述-1 || DELTAX→1 ||移动deltaY&所述-1 ||移动deltaY→1){
滚动(-deltaX,移动deltaY);
lastTouchX = X;
lastTouchY = Y;
无效();
}
}
公共无效onTouchUp(浮X,浮动Y){
最终浮动规模=宽/ gwidth;
浮SX = -touchHandler.velocityTracker.getXVelocity();
浮SY = touchHandler.velocityTracker.getYVelocity();
最终浮动ASX = Math.abs(SX);
最终浮动ASY = Math.abs(SY);
如果(ASX< ASY / 3){
SX = 0;
}否则如果(ASY< ASX / 3){
SY = 0;
}
scroller.fling(Math.round(currentX *标度),
Math.round(currentY *等级),Math.round(SX),Math.round(SY)
-10000,10000,-10000,10000);
无效();
}
公共无效onTouchZoomDown(浮动X1,Y1浮球,浮球X2,浮动Y2){
zoomTracker.start(gwidth,X1,Y1,X2,Y2);
}
公共无效onTouchZoomMove(浮动X1,Y1浮球,浮球X2,浮动Y2){
如果(!zoomTracker.update(X1,Y1,X2,Y2)){
返回;
}
浮targetGwidth = zoomTracker.value;
如果(targetGwidth> .25f&安培;&安培; targetGwidth&所述; 200){
gwidth = targetGwidth;
}
invalidateGraphs();
}
私人无效滚动(浮动DELTAX,漂浮移动deltaY){
最终浮动规模= gwidth /宽;
浮DX = DELTAX *规模;
浮DY =移动deltaY *规模;
最终浮动ADX = Math.abs(DX);
最终浮动安以轩= Math.abs(DY);
如果(ADX<安以轩/ 3){
DX = 0;
}否则如果(安以轩< ADX / 3){
DY = 0;
}
currentX + = DX;
currentY + = DY;
}
}
XML编辑器的错误日志
显示java.lang.NullPointerException
在android.widget.ZoomButtonsController.createContainer(ZoomButtonsController.java:266)
在android.widget.ZoomButtonsController< INIT>(ZoomButtonsController.java:212)
在calculator.GraphView< INIT>(GraphView.java:43)
在sun.reflect.NativeConstructorAccessorImpl.newInstance0(在sun.reflect.NativeConstructorAccessorImpl.newInstance(在sun.reflect.DelegatingConstructorAccessorImpl.newInstance(在java.lang.reflect.Constructor.newInstance(在com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.instantiateClass(ProjectCallback.java:422)
在com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.loadView(ProjectCallback.java:179)
在android.view.BridgeInflater.loadCustomView(BridgeInflater.java:207)
在android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:135)
在android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:746)
在android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:64)
在android.view.LayoutInflater.rInflate(LayoutInflater.java:718)
在android.view.LayoutInflater.inflate(LayoutInflater.java:489)
在android.view.LayoutInflater.inflate(LayoutInflater.java:372)
解决方案
isInEditMode()
应内部的自定义视图构造函数中使用。
试试下面的code:
公共类GraphView扩展视图实现绘图
{
公共GraphView(上下文的背景下,ATTRS的AttributeSet){
超(背景下,ATTRS);
如果(!isInEditMode())
的init(上下文);
}
公共GraphView(上下文的背景下){
超(上下文);
如果(!isInEditMode()){
touchHandler =新TouchHandler(本);
的init(上下文);
}
}
I must edit a software that have a custom view, when I try to edit layout xml, Eclipse says me:
Use View.isInEditMode() in your custom views to skip code when shown in Eclipse
But I have no idea about how and where I must use isInEditMode() in the app
My xml file is
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ff000000"
>
<TextView
android:id="@+id/result"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:textSize="32dip"
android:scrollbars="none"
android:lines="1"
android:freezesText="true"
android:textColor="@color/result"
/>
<EditText
android:id="@+id/input"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:textSize="28dip"
android:scrollbars="none"
android:singleLine="true"
android:autoText="false"
android:imeOptions="flagNoEnterAction|flagNoExtractUi"
/>
<ListView
android:id="@+id/history"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:cacheColorHint="#ff000000"
android:choiceMode="singleChoice"
android:scrollbarStyle="outsideInset"
android:scrollbars="none"
/>
<calculator.GraphView
android:id="@+id/graph"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:visibility="gone"
/>
<include layout="@layout/keyboard" />
</LinearLayout>
And my GraphView is
public class GraphView extends View implements Grapher,
ZoomButtonsController.OnZoomListener,
TouchHandler.TouchHandlerInterface {
private int width, height;
private Matrix matrix = new Matrix();
private Paint paint = new Paint();
private Paint textPaint = new Paint();
private ArrayList<Function> funcs = new ArrayList<Function>();
private Data next = new Data(), endGraph = new Data();
private Data graphs[] = { new Data(), new Data(), new Data(), new Data(),
new Data() };
private static final int GRAPHS_SIZE = 5;
private float gwidth = 8;
private float currentX, currentY;
private float lastMinX;
private Scroller scroller;
private float boundMinY, boundMaxY;
protected ZoomButtonsController zoomController = new ZoomButtonsController(
this);
private ZoomTracker zoomTracker = new ZoomTracker();
private TouchHandler touchHandler;
private float lastTouchX, lastTouchY;
private static final int COL_AXIS = 0xff00a000, COL_GRID = 0xff004000,
COL_TEXT = 0xff00ff00;
private static final int COL_GRAPH[] = { 0xffffffff, 0xff00ffff,
0xffffff00, 0xffff00ff, 0xff80ff80 };
public GraphView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public GraphView(Context context) {
super(context);
touchHandler = new TouchHandler(this);
init(context);
}
private void init(Context context) {
zoomController.setOnZoomListener(this);
scroller = new Scroller(context);
paint.setAntiAlias(false);
textPaint.setAntiAlias(true);
}
@SuppressLint("WrongCall")
public String captureScreenshot() {
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
onDraw(canvas);
return Util.saveBitmap(bitmap, Grapher.SCREENSHOT_DIR, "calculator");
}
private void clearAllGraph() {
for (int i = 0; i < GRAPHS_SIZE; ++i) {
graphs[i].clear();
}
}
public void setFunctions(ArrayList<Function> fs) {
funcs.clear();
for (Function f : fs) {
int arity = f.arity();
if (arity == 0 || arity == 1) {
funcs.add(f);
}
}
clearAllGraph();
invalidate();
}
public void setFunction(Function f) {
funcs.clear();
if (f != null) {
funcs.add(f);
}
clearAllGraph();
invalidate();
}
public void onVisibilityChanged(boolean visible) {
}
public void onZoom(boolean zoomIn) {
if (zoomIn) {
if (canZoomIn()) {
gwidth /= 2;
invalidateGraphs();
}
} else {
if (canZoomOut()) {
gwidth *= 2;
invalidateGraphs();
}
}
zoomController.setZoomInEnabled(canZoomIn());
zoomController.setZoomOutEnabled(canZoomOut());
}
public void onResume() {
}
public void onPause() {
}
public void onDetachedFromWindow() {
zoomController.setVisible(false);
super.onDetachedFromWindow();
}
protected void onSizeChanged(int w, int h, int ow, int oh) {
width = w;
height = h;
clearAllGraph();
}
protected void onDraw(Canvas canvas) {
if (funcs.size() == 0) {
return;
}
if (scroller.computeScrollOffset()) {
final float scale = gwidth / width;
currentX = scroller.getCurrX() * scale;
currentY = scroller.getCurrY() * scale;
if (!scroller.isFinished()) {
invalidate();
}
}
drawGraph(canvas);
}
private float eval(Function f, float x) {
float v = (float) f.eval(x);
if (v < -10000f) {
return -10000f;
}
if (v > 10000f) {
return 10000f;
}
return v;
}
private float distance2(float x1, float y1, float x2, float y2, float y) {
final float dx = x2 - x1;
final float dy = y2 - y1;
final float up = dx * (y1 + y2 - y - y);
return up * up / (dx * dx + dy * dy);
}
private void computeGraph(Function f, float minX, float maxX, float minY,
float maxY, Data graph) {
if (f.arity() == 0) {
float v = (float) f.eval();
if (v < -10000f) {
v = -10000f;
}
if (v > 10000f) {
v = 10000f;
}
graph.clear();
graph.push(minX, v);
graph.push(maxX, v);
return;
}
final float scale = width / gwidth;
final float maxStep = 15.8976f / scale;
final float minStep = .05f / scale;
float ythresh = 1 / scale;
ythresh = ythresh * ythresh;
if (!graph.empty()) {
if (minX >= lastMinX) {
graph.eraseBefore(minX);
} else {
graph.eraseAfter(maxX);
maxX = Math.min(maxX, graph.firstX());
graph.swap(endGraph);
}
}
if (graph.empty()) {
graph.push(minX, eval(f, minX));
}
float leftX, leftY;
float rightX = graph.topX(), rightY = graph.topY();
int nEval = 1;
while (true) {
leftX = rightX;
leftY = rightY;
if (leftX > maxX) {
break;
}
if (next.empty()) {
float x = leftX + maxStep;
next.push(x, eval(f, x));
++nEval;
}
rightX = next.topX();
rightY = next.topY();
next.pop();
if (leftY != leftY && rightY != rightY) { // NaN
continue;
}
float dx = rightX - leftX;
float middleX = (leftX + rightX) / 2;
float middleY = eval(f, middleX);
++nEval;
boolean middleIsOutside = (middleY < leftY && middleY < rightY)
|| (leftY < middleY && rightY < middleY);
if (dx < minStep) {
if (middleIsOutside) {
graph.push(rightX, Float.NaN);
}
graph.push(rightX, rightY);
continue;
}
if (middleIsOutside
&& ((leftY < minY && rightY > maxY) || (leftY > maxY && rightY < minY))) {
graph.push(rightX, Float.NaN);
graph.push(rightX, rightY);
continue;
}
if (!middleIsOutside) {
if (distance2(leftX, leftY, rightX, rightY, middleY) < ythresh) {
graph.push(rightX, rightY);
continue;
}
}
next.push(rightX, rightY);
next.push(middleX, middleY);
rightX = leftX;
rightY = leftY;
}
if (!endGraph.empty()) {
graph.append(endGraph);
}
long t2 = System.currentTimeMillis();
next.clear();
endGraph.clear();
}
private static Path path = new Path();
private Path graphToPath(Data graph) {
boolean first = true;
int size = graph.size;
float[] xs = graph.xs;
float[] ys = graph.ys;
path.rewind();
for (int i = 0; i < size; ++i) {
float y = ys[i];
float x = xs[i];
// Calculator.log("path " + x + ' ' + y);
if (y == y) { // !NaN
if (first) {
path.moveTo(x, y);
first = false;
} else {
path.lineTo(x, y);
}
} else {
first = true;
}
}
return path;
}
private static final float NTICKS = 15;
private static float stepFactor(float w) {
float f = 1;
while (w / f > NTICKS) {
f *= 10;
}
while (w / f < NTICKS / 10) {
f /= 10;
}
float r = w / f;
if (r < NTICKS / 5) {
return f / 5;
} else if (r < NTICKS / 2) {
return f / 2;
} else {
return f;
}
}
private static StringBuilder b = new StringBuilder();
private static char[] buf = new char[20];
private static StringBuilder format(float fv) {
int pos = 0;
boolean addDot = false;
int v = Math.round(fv * 100);
boolean isNeg = v < 0;
v = isNeg ? -v : v;
for (int i = 0; i < 2; ++i) {
int digit = v % 10;
v /= 10;
if (digit != 0 || addDot) {
buf[pos++] = (char) ('0' + digit);
addDot = true;
}
}
if (addDot) {
buf[pos++] = '.';
}
if (v == 0) {
buf[pos++] = '0';
}
while (v != 0) {
buf[pos++] = (char) ('0' + (v % 10));
v /= 10;
}
if (isNeg) {
buf[pos++] = '-';
}
b.setLength(0);
b.append(buf, 0, pos);
b.reverse();
return b;
}
private void drawGraph(Canvas canvas) {
long t1 = System.currentTimeMillis();
float minX = currentX - gwidth / 2;
float maxX = minX + gwidth;
float ywidth = gwidth * height / width;
float minY = currentY - ywidth / 2;
float maxY = minY + ywidth;
if (minY < boundMinY || maxY > boundMaxY) {
float halfw = ywidth / 2;
boundMinY = minY - halfw;
boundMaxY = maxY + halfw;
clearAllGraph();
}
canvas.drawColor(0xff000000);
paint.setStrokeWidth(0);
paint.setAntiAlias(false);
paint.setStyle(Paint.Style.STROKE);
final float h2 = height / 2f;
final float scale = width / gwidth;
float x0 = -minX * scale;
boolean drawYAxis = true;
if (x0 < 25) {
x0 = 25;
// drawYAxis = false;
} else if (x0 > width - 3) {
x0 = width - 3;
// drawYAxis = false;
}
float y0 = maxY * scale;
if (y0 < 3) {
y0 = 3;
} else if (y0 > height - 15) {
y0 = height - 15;
}
final float tickSize = 3;
final float y2 = y0 + tickSize;
paint.setColor(COL_GRID);
float step = stepFactor(gwidth);
float v = ((int) (minX / step)) * step;
textPaint.setColor(COL_TEXT);
textPaint.setTextSize(12);
textPaint.setTextAlign(Paint.Align.CENTER);
float stepScale = step * scale;
for (float x = (v - minX) * scale; x <= width; x += stepScale, v += step) {
canvas.drawLine(x, 0, x, height, paint);
if (!(-.001f < v && v < .001f)) {
StringBuilder b = format(v);
canvas.drawText(b, 0, b.length(), x, y2 + 10, textPaint);
}
}
final float x1 = x0 - tickSize;
v = ((int) (minY / step)) * step;
textPaint.setTextAlign(Paint.Align.RIGHT);
for (float y = height - (v - minY) * scale; y >= 0; y -= stepScale, v += step) {
canvas.drawLine(0, y, width, y, paint);
if (!(-.001f < v && v < .001f)) {
StringBuilder b = format(v);
canvas.drawText(b, 0, b.length(), x1, y + 4, textPaint);
}
}
paint.setColor(COL_AXIS);
if (drawYAxis) {
canvas.drawLine(x0, 0, x0, height, paint);
}
canvas.drawLine(0, y0, width, y0, paint);
matrix.reset();
matrix.preTranslate(-currentX, -currentY);
matrix.postScale(scale, -scale);
matrix.postTranslate(width / 2, height / 2);
paint.setStrokeWidth(0);
paint.setAntiAlias(false);
int n = Math.min(funcs.size(), GRAPHS_SIZE);
for (int i = 0; i < n; ++i) {
computeGraph(funcs.get(i), minX, maxX, boundMinY, boundMaxY,
graphs[i]);
Path path = graphToPath(graphs[i]);
path.transform(matrix);
paint.setColor(COL_GRAPH[i]);
canvas.drawPath(path, paint);
}
lastMinX = minX;
}
private boolean canZoomIn() {
return gwidth > 1f;
}
private boolean canZoomOut() {
return gwidth < 50;
}
private void invalidateGraphs() {
clearAllGraph();
boundMinY = boundMaxY = 0;
invalidate();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return touchHandler != null ? touchHandler.onTouchEvent(event) : super
.onTouchEvent(event);
}
public void onTouchDown(float x, float y) {
zoomController.setVisible(true);
if (!scroller.isFinished()) {
scroller.abortAnimation();
}
lastTouchX = x;
lastTouchY = y;
}
public void onTouchMove(float x, float y) {
float deltaX = x - lastTouchX;
float deltaY = y - lastTouchY;
if (deltaX < -1 || deltaX > 1 || deltaY < -1 || deltaY > 1) {
scroll(-deltaX, deltaY);
lastTouchX = x;
lastTouchY = y;
invalidate();
}
}
public void onTouchUp(float x, float y) {
final float scale = width / gwidth;
float sx = -touchHandler.velocityTracker.getXVelocity();
float sy = touchHandler.velocityTracker.getYVelocity();
final float asx = Math.abs(sx);
final float asy = Math.abs(sy);
if (asx < asy / 3) {
sx = 0;
} else if (asy < asx / 3) {
sy = 0;
}
scroller.fling(Math.round(currentX * scale),
Math.round(currentY * scale), Math.round(sx), Math.round(sy),
-10000, 10000, -10000, 10000);
invalidate();
}
public void onTouchZoomDown(float x1, float y1, float x2, float y2) {
zoomTracker.start(gwidth, x1, y1, x2, y2);
}
public void onTouchZoomMove(float x1, float y1, float x2, float y2) {
if (!zoomTracker.update(x1, y1, x2, y2)) {
return;
}
float targetGwidth = zoomTracker.value;
if (targetGwidth > .25f && targetGwidth < 200) {
gwidth = targetGwidth;
}
invalidateGraphs();
}
private void scroll(float deltaX, float deltaY) {
final float scale = gwidth / width;
float dx = deltaX * scale;
float dy = deltaY * scale;
final float adx = Math.abs(dx);
final float ady = Math.abs(dy);
if (adx < ady / 3) {
dx = 0;
} else if (ady < adx / 3) {
dy = 0;
}
currentX += dx;
currentY += dy;
}
}
The error Log of the XML editor
java.lang.NullPointerException
at android.widget.ZoomButtonsController.createContainer(ZoomButtonsController.java:266)
at android.widget.ZoomButtonsController.<init>(ZoomButtonsController.java:212)
at calculator.GraphView.<init>(GraphView.java:43)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0( at sun.reflect.NativeConstructorAccessorImpl.newInstance( at sun.reflect.DelegatingConstructorAccessorImpl.newInstance( at java.lang.reflect.Constructor.newInstance( at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.instantiateClass(ProjectCallback.java:422)
at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.loadView(ProjectCallback.java:179)
at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:207)
at android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:135)
at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:746)
at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:64)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:718)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:372)
解决方案
isInEditMode()
should be used inside the Custom View constructor.
Try the following code:
public class GraphView extends View implements Grapher
{
public GraphView(Context context, AttributeSet attrs) {
super(context, attrs);
if(!isInEditMode())
init(context);
}
public GraphView(Context context) {
super(context);
if(!isInEditMode()){
touchHandler = new TouchHandler(this);
init(context);
}
}
这篇关于如何使用isInEditMode(),看看在编辑器中使用自定义视图布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文