【问题标题】:Android - adding a custom view to scroll view where the custom view is an inner classAndroid - 将自定义视图添加到自定义视图是内部类的滚动视图
【发布时间】:2013-03-06 16:10:33
【问题描述】:

我一直在尝试使我的应用程序能够滚动我的自定义视图(水平和垂直),以使用户能够绘制的不仅仅是初始屏幕大小。该应用程序将用于生成基本的房屋计划,例如用户绘制连接的矩形代表他们的家。

我正在使用我在活动中设置(作为内部类)的自定义视图。在广泛搜索并看到人们在滚动视图中遇到的问题之后,这是我所能得到的。这是我的 XML:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >
    <com.example.HomerProject1stDraft.DrawNewPlans.HomerView
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </com.example.HomerProject1stDraft.DrawNewPlans.HomerView>
</LinearLayout>

如您所见,我正在尝试添加 HomerView 类,该类位于 DrawNewPlans 类(活动)中。

这里是onCreate() 方法:

protected void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState);
    setContentView(R.layout.drawnew);
}

这是我的自定义视图的代码(记住它包含在另一个类中):

    class HomerView extends View { // the custom View for drawing on
    // set up Bitmap, canvas, path and paint
    private Bitmap myBitmap; // the initial image we turn into our canvas
    private Canvas myCanvas; // the canvas we are drawing on
    private Rect myRect; // the mathematical path of the lines we draw
    private Paint myBitmapPaint; // the paint we use to draw the bitmap

    // get the width of the entire tablet screen
    private int screenWidth = getContext().getResources()
            .getDisplayMetrics().widthPixels;
    // get the height of the entire tablet screen
    private int screenHeight = (getContext().getResources()
            .getDisplayMetrics().heightPixels);

    private int mX, mY, iX, iY; // current x,y and in

    public HomerView(Context context) { // constructor of HomerView
        super(context);
        System.out.println("Screen Width = "+screenWidth+" and screen height = "+screenHeight);
        myBitmap = Bitmap.createBitmap(screenWidth, screenHeight,
                Bitmap.Config.ARGB_8888); // set our drawable space - the bitmap which becomes the canvas we draw on
        myCanvas = new Canvas(myBitmap); // set our canvas to our bitmap which we just set up
        myRect = new Rect(); // make a new rect
        myBitmapPaint = new Paint(Paint.DITHER_FLAG); // set dither to ON in our saved drawing - gives better color interaction
    }


    protected void onDraw(Canvas canvas) { // method used when we want to draw something to our canvas
        super.onDraw(canvas);
        if (addObjectMode == true || addApplianceMode == true) {
            canvas.drawColor(Color.TRANSPARENT); // sets canvas colour
            canvas.drawBitmap(myBitmap, 0, 0, myBitmapPaint); // save the canvas to bitmap - the numbers are the x, y coords we are drawing from
            for (int i = 0; i < rectList.size(); i++) {
                canvas.drawRect(rectList.get(i), myPaint);
            }
            if (addApplianceMode == true) {
                canvas.drawBitmap(bmp, iX-50, iY-50, myBitmapPaint);
            }
            canvas.drawRect(myRect, myPaint); // draw the rectangle that the user has drawn using the paint we set up
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { // if screen size changes, alter the bitmap size
        super.onSizeChanged(w, h, oldw, oldh);
    }

    private void touch_Start(float x, float y) { // on finger touchdown
        // check touch mode
        iX = (int) (Math.round(x));
        iY = (int) (Math.round(y));
        mX = (int) (Math.round(x));
        mY = (int) (Math.round(y));
        if (addObjectMode == true) {
            myRect.set(iX, iY, mX, mY);
        } else if (addApplianceMode == true) {
            // code to draw an appliance icon at mX, mY (with offset so icon is centered)
            if (isLamp == true) {
                Resources res = getResources();
                bmp = BitmapFactory.decodeResource(res, R.drawable.lamp);
                myCanvas.drawBitmap(bmp, iX - 50, iY - 50, myBitmapPaint);
            } else if (isPC == true) {
                Resources res = getResources();
                bmp = BitmapFactory.decodeResource(res, R.drawable.pc);
                myCanvas.drawBitmap(bmp, iX - 50, iY - 50, myBitmapPaint);
            } else if (isKettle == true) {
                Resources res = getResources();
                bmp = BitmapFactory.decodeResource(res, R.drawable.kettle);
                myCanvas.drawBitmap(bmp, iX - 50, iY - 50, myBitmapPaint);
            } else if (isOven == true) {
                Resources res = getResources();
                bmp = BitmapFactory.decodeResource(res, R.drawable.oven);
                myCanvas.drawBitmap(bmp, iX - 50, iY - 50, myBitmapPaint);
            } else if (isTV == true) {
                Resources res = getResources();
                bmp = BitmapFactory.decodeResource(res, R.drawable.tv);
                myCanvas.drawBitmap(bmp, iX - 50, iY - 50, myBitmapPaint);
            }
        }
    }

    private void touch_Move(float x, float y) { // on finger movement
        float dX = Math.abs(x - mX); // get difference between x and my X
        float dY = Math.abs(y - mY);
        if (dX >= TOUCH_TOLERANCE || dY >= TOUCH_TOLERANCE) { // if coordinates are outside screen? if touching hard enough?
            mX = (int) (Math.round(x));
            mY = (int) (Math.round(y));
            if (addObjectMode == true) {
                myRect.set(iX, iY, mX, mY);
            }
        }
    }

    @SuppressWarnings("deprecation")
    private void touch_Up() { // on finger release
        if (addObjectMode == true) {
            myRect.set(iX, iY, mX, mY);
            System.out.println("MyRect coords = "+iX+","+iY+","+mX+","+mY);
            rectList.add(myRect);
            myCanvas.drawRect(iX, iY, mX, mY, myPaint); // if this isnt present - no lasting copy is drawn to screen. It is erased every draw.
            if (eraseMode == false) {
                dialogStarter();
            }
        } else if (addApplianceMode == true) {
            showDialog(DIALOG_DEVICE_ENTRY);
        }
    }

    public boolean onTouchEvent(MotionEvent event) { // on any touch event
        if (addObjectMode == true || addApplianceMode == true) {

            float x = event.getX(); // get current X
            float y = event.getY(); // get current Y

            switch (event.getAction()) { // what action is the user performing?
            case MotionEvent.ACTION_DOWN: // if user is touching down
                touch_Start(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE: // if user is moving finger while touched down
                touch_Move(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP: // if user has released finger
                touch_Up();
                invalidate();
                break;
            }
            return true;
        } else {
            return false;
        }
    }
}

我意识到我需要添加很多东西 - 但它们是什么? awakenScrollBars()?

另外:目前我在 XML 文件中收到此错误 Error inflating class com.example.HomerProject1stDraft.DrawNewPlans.HomerView。我创建自定义视图的方式是否有错误?您甚至可以从内部类创建视图吗?

非常感谢。

【问题讨论】:

    标签: android xml inner-classes android-custom-view android-scrollview


    【解决方案1】:

    首先,我建议不要将您的自定义滚动视图包装在另一个滚动视图中。如果可以避免,请避免使用它。此外,您可以查看下面我已实现自定义滚动视图的链接。

    https://stackoverflow.com/questions/15188842/customization-of-imageview-and-layouts

    【讨论】:

    • 抱歉,应该指定 - 自定义视图不是滚动视图。我会附上代码。
    【解决方案2】:

    ScrollView 只支持垂直滚动。您需要在水平和垂直两侧滚动,因为您需要一个称为 TwoDScrollView 的特殊类。

    有关此类和源代码的更多信息,请访问: http://blog.gorges.us/2010/06/android-two-dimensional-scrollview/

    在您的 xml 中使用此类而不是 ScrollView,您应该能够水平和垂直滚动。

    对于您的其他错误,请分享源代码并说明您遇到问题的位置。

    【讨论】:

    • 错误似乎是 xml 添加我的自定义视图的行 - 。感谢您提供有关仅垂直滚动的提示。
    猜你喜欢
    • 2023-03-08
    • 1970-01-01
    • 2014-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多