Erstellen einer beziehbaren und zoombaren Bildansicht in Android

Tor:

Erstellen Sie eine Bildansicht, die zeichnbar und zoombar ist,

Das heißt, wenn ich einen Knopf drücke, ist es ausziehbar,

Oder wenn ich abschalte, ist das zoombar.

* Beachten Sie die Zeichnungen sollte Zoom mit der Bildansicht zu vergrößern

========================================== =============

In letzter Zeit habe ich eine kundenspezifische Bildansicht wie folgt geschrieben:

public class DrawView extends ImageView { private int color = Color.BLACK; private float width = 4f; private List<Holder> holderList = new ArrayList<Holder>(); private class Holder { Path path; Paint paint; Holder(int color, float width) { path = new Path(); paint = new Paint(); paint.setAntiAlias(true); paint.setStrokeWidth(width); paint.setColor(color); paint.setStyle(Paint.Style.STROKE); paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeCap(Paint.Cap.ROUND); } } public DrawView(Context context) { super(context); init(); } public DrawView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public DrawView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { holderList.add(new Holder(color, width)); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (Holder holder : holderList) { canvas.drawPath(holder.path, holder.paint); } } @Override public boolean onTouchEvent(MotionEvent event) { float eventX = event.getX(); float eventY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: holderList.add(new Holder(color,width)); holderList.get(holderList.size() - 1).path.moveTo(eventX, eventY); return true; case MotionEvent.ACTION_MOVE: holderList.get(holderList.size() - 1).path.lineTo(eventX, eventY); break; case MotionEvent.ACTION_UP: break; default: return false; } invalidate(); return true; } public void resetPaths() { for (Holder holder : holderList) { holder.path.reset(); } invalidate(); } public void setBrushColor(int color) { this.color = color; } public void setWidth(float width) { this.width = width; } } 

Und das XML ist:

 <com.example.tool.DrawView android:id="@+id/draw" android:layout_width="match_parent" android:layout_height="match_parent" android:adjustViewBounds="true" /> 

Das Problem ist, wie man es auch zoom-fähig macht ? Beachten Sie , dass die Zeichnungen beim Zoomen mit der Bildansicht übereinstimmen sollten .

Versuche, eine benutzerdefinierte Imageview-Bibliothek zu benutzen, aber kein Glück.

Z. B. Wenn ich photoview verwende, kann es zoomen, aber die Zeichnungen richten sich nicht aus und die Zoomstufe wird zurückgesetzt, nachdem ich das Zoomen ein- / ausschaltet. Https://github.com/chrisbanes/PhotoView

Auch finden Sie eine andere Bibliothek so, aber nicht passen die benutzerdefinierte Ansicht Fall https://github.com/matabii/scale-imageview-android

Bildbeschreibung hier eingeben

Update1: Demo

Empfohlen, diese App zu verweisen, ist die Zeichnungsfunktion eigentlich die gleiche wie das, was ich kämpfe, um zu erreichen, aber ich kann nicht herausfinden, wie sie es fertig machen

Https://play.google.com/store/apps/details?id=com.zentertain.photoeditor&hl=de

Vielen Dank

Update2: Von Sandeep Maram Quelle

Vielen Dank Sandeep Maram, nach dem Testen des Codes, alles funktioniert gut, das einzige, was bleibt, ist die Zeichnung nicht mit der Zoom-Ansicht ausrichten. Bitte werfen Sie einen Blick auf den Screenshot

Vor: Bildbeschreibung hier eingeben

Nach:

Bildbeschreibung hier eingeben

Der Kreis ist nicht Skala oben / unten, wenn Zoom, wäre wirklich nett wenn fix das. Auch das ist egal, ob das Bild den Knopf überlappt.

  • Kann eine ziehbare Form haben, ist die Größe auf fill_parent gesetzt?
  • Form Drawable gradientRadius funktioniert nur in Pixeln. Ist das nicht nutzlos % Werte funktionieren nicht
  • Resources gibt eine Zeichenkette des falschen Typs zurück
  • Die Ressource @ drawable / homebackground konnte nicht gelöst werden
  • Wie konvertiere ich eine Zeichenkette in eine Bitmap?
  • Ist es möglich, Festplatten in Android API vor 23 zu erstellen?
  • Wie kann man eine Layer-Liste zeichnen?
  • Erstellen Sie einen benutzerdefinierten Hintergrund für einen EditText
  • 2 Solutions collect form web for “Erstellen einer beziehbaren und zoombaren Bildansicht in Android”

    Antwort aktualisiert mit Zoom Aktivieren / Deaktivieren und Zeichnen

    Activity_main.xml

     <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <Button android:id="@+id/enable_zoom" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="disable zoom"/> <com.rbt.zoomdraw.CustomImageView android:id="@+id/zoom_iv" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/ic_launcher" android:layout_below="@+id/enable_zoom" /> <com.rbt.zoomdraw.DrawableView android:id="@+id/drawble_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignBottom="@+id/zoom_iv" android:layout_alignTop="@+id/zoom_iv" /> 

    MainActivity.java

     public class MainActivity extends Activity implements OnClickListener { private Button enableZoomBtn; private DrawableView drawbleView; private CustomImageView touchImageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); drawbleView = (DrawableView) findViewById(R.id.drawble_view); enableZoomBtn = (Button) findViewById(R.id.enable_zoom); touchImageView = (CustomImageView) findViewById(R.id.zoom_iv); enableZoomBtn.setOnClickListener(this); drawbleView.setDrawingEnabled(false); } @Override public void onClick(View v) { int id = v.getId(); switch (id) { case R.id.enable_zoom: if(enableZoomBtn.getText().equals("disable zoom")){ touchImageView.setZoomEnable(false); drawbleView.setDrawingEnabled(true); enableZoomBtn.setText("enable zoom"); } else{ touchImageView.setZoomEnable(true); drawbleView.setDrawingEnabled(false); enableZoomBtn.setText("disable zoom"); } break; default: break; } } } 

    DrawableView.java

     public class DrawableView extends View { public int width; public int height; private boolean isEditable; private Path drawPath; private Paint drawPaint; private Paint canvasPaint; private Canvas drawCanvas; private Bitmap canvasBitmap; private int paintColor = Color.RED; public DrawableView(Context context) { super(context); } public DrawableView(Context context, AttributeSet attrs) { super(context, attrs); this.canvasPaint = new Paint(Paint.DITHER_FLAG); setupDrawing(); } public DrawableView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); this.height = h; this.width = w; canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); drawCanvas = new Canvas(canvasBitmap); } private void setupDrawing() { drawPath = new Path(); drawPaint = new Paint(); drawPaint.setColor(paintColor); drawPaint.setAntiAlias(true); drawPaint.setDither(true); drawPaint.setStyle(Paint.Style.STROKE); drawPaint.setStrokeJoin(Paint.Join.ROUND); drawPaint.setStrokeCap(Paint.Cap.ROUND); drawPaint.setStrokeWidth(10); } public void setDrawingEnabled(boolean isEditable){ this.isEditable = isEditable; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint); canvas.drawPath(drawPath, drawPaint); } @Override public boolean onTouchEvent(MotionEvent event) { if(isEditable){ float touchX = event.getX(); float touchY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: drawPath.moveTo(touchX, touchY); break; case MotionEvent.ACTION_MOVE: drawPath.lineTo(touchX, touchY); break; case MotionEvent.ACTION_UP: drawPath.lineTo(touchX, touchY); drawCanvas.drawPath(drawPath, drawPaint); drawPath = new Path(); break; default: return false; } } else{ return false; } invalidate(); return true; } } 

    CustomImageView

     public class CustomImageView extends ImageView { Matrix matrix; // We can be in one of these 3 states static final int NONE = 0; static final int DRAG = 1; static final int ZOOM = 2; int mode = NONE; private boolean zoomEnable= true; // Remember some things for zooming PointF last = new PointF(); PointF start = new PointF(); float minScale = 1f; float maxScale = 5f; float[] m; int viewWidth, viewHeight; static final int CLICK = 3; float saveScale = 1f; protected float origWidth, origHeight; int oldMeasuredWidth, oldMeasuredHeight; ScaleGestureDetector mScaleDetector; Context context; public CustomImageView(Context context) { super(context); sharedConstructing(context); } public void setZoomEnable(boolean status){ zoomEnable = status; } public CustomImageView(Context context, AttributeSet attrs) { super(context, attrs); sharedConstructing(context); } private void sharedConstructing(Context context) { super.setClickable(true); this.context = context; mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); matrix = new Matrix(); m = new float[9]; setImageMatrix(matrix); setScaleType(ScaleType.MATRIX); setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if(zoomEnable){ mScaleDetector.onTouchEvent(event); PointF curr = new PointF(event.getX(), event.getY()); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: last.set(curr); start.set(last); mode = DRAG; break; case MotionEvent.ACTION_MOVE: if (mode == DRAG) { float deltaX = curr.x - last.x; float deltaY = curr.y - last.y; float fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale); float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale); matrix.postTranslate(fixTransX, fixTransY); fixTrans(); last.set(curr.x, curr.y); } break; case MotionEvent.ACTION_UP: mode = NONE; int xDiff = (int) Math.abs(curr.x - start.x); int yDiff = (int) Math.abs(curr.y - start.y); if (xDiff < CLICK && yDiff < CLICK) performClick(); break; case MotionEvent.ACTION_POINTER_UP: mode = NONE; break; } setImageMatrix(matrix); invalidate(); return true; // indicate event was handled } else{ return false; } } }); } public void setMaxZoom(float x) { maxScale = x; } private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScaleBegin(ScaleGestureDetector detector) { mode = ZOOM; return true; } @Override public boolean onScale(ScaleGestureDetector detector) { float mScaleFactor = detector.getScaleFactor(); float origScale = saveScale; saveScale *= mScaleFactor; if (saveScale > maxScale) { saveScale = maxScale; mScaleFactor = maxScale / origScale; } else if (saveScale < minScale) { saveScale = minScale; mScaleFactor = minScale / origScale; } if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight) matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2); else matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY()); fixTrans(); return true; } } void fixTrans() { matrix.getValues(m); float transX = m[Matrix.MTRANS_X]; float transY = m[Matrix.MTRANS_Y]; float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale); float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale); if (fixTransX != 0 || fixTransY != 0) matrix.postTranslate(fixTransX, fixTransY); } float getFixTrans(float trans, float viewSize, float contentSize) { float minTrans, maxTrans; if (contentSize <= viewSize) { minTrans = 0; maxTrans = viewSize - contentSize; } else { minTrans = viewSize - contentSize; maxTrans = 0; } if (trans < minTrans) return -trans + minTrans; if (trans > maxTrans) return -trans + maxTrans; return 0; } float getFixDragTrans(float delta, float viewSize, float contentSize) { if (contentSize <= viewSize) { return 0; } return delta; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); viewWidth = MeasureSpec.getSize(widthMeasureSpec); viewHeight = MeasureSpec.getSize(heightMeasureSpec); // // Rescales image on rotation // if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight || viewWidth == 0 || viewHeight == 0) return; oldMeasuredHeight = viewHeight; oldMeasuredWidth = viewWidth; if (saveScale == 1) { // Fit to screen. float scale; Drawable drawable = getDrawable(); if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0) return; int bmWidth = drawable.getIntrinsicWidth(); int bmHeight = drawable.getIntrinsicHeight(); Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight); float scaleX = (float) viewWidth / (float) bmWidth; float scaleY = (float) viewHeight / (float) bmHeight; scale = Math.min(scaleX, scaleY); matrix.setScale(scale, scale); // Center the image float redundantYSpace = (float) viewHeight - (scale * (float) bmHeight); float redundantXSpace = (float) viewWidth - (scale * (float) bmWidth); redundantYSpace /= (float) 2; redundantXSpace /= (float) 2; matrix.postTranslate(redundantXSpace, redundantYSpace); origWidth = viewWidth - 2 * redundantXSpace; origHeight = viewHeight - 2 * redundantYSpace; setImageMatrix(matrix); } fixTrans(); } } 

    Ich hoffe es wird für dich arbeiten

    Ich habe keine komplette Lösung. Allerdings kann ich Ihnen vorschlagen, einen Blick auf PhotoView zu werfen, der eine Zoom-Implementierung und meine benutzerdefinierte CanvasView die ich in einem der alten Projekte verwendete. Es erlaubt, mit "Stift" -Tool zu zeichnen und Text auf sie zu schreiben. Text-Funktion ist für Sie unnötig und wahrscheinlich war zu spezifisch für diesen Teil, so dass Sie es überspringen können. Vielleicht hilft es dir. Es unterstützt die Siebrotation, was zu neuen ziehbaren Abmessungen führt und sowohl Text als auch Kurven in diesem Fall skaliert werden.

     public class CanvasView extends View { // ----------------------------------------------------------------------- // // Constants // // ----------------------------------------------------------------------- @SuppressWarnings("unused") private static final String TAG = CanvasView.class.getSimpleName(); private static final String EXTRA_SUPER_STATE = "EXTRA_SUPER_STATE"; private static final String EXTRA_COLOR = "EXTRA_COLOR"; private static final String EXTRA_ACTION = "EXTRA_ACTION"; private static final String EXTRA_MODIFICATIONS = "EXTRA_MODIFICATIONS"; private static final String EXTRA_CURRENT_MODIFICATION = "EXTRA_CURRENT_MODIFICATION"; // ----------------------------------------------------------------------- // // Enums // // ----------------------------------------------------------------------- public static enum ACTION { PEN, TEXT }; // ----------------------------------------------------------------------- // // Fields // // ----------------------------------------------------------------------- private ArrayList<DrawableItem> mItems; private ACTION mAction; private int mColor; private float mDensityScale; private DrawableItem mCurrentItem; private EditText mEditText; // ----------------------------------------------------------------------- // // Constructor // // ----------------------------------------------------------------------- public CanvasView(Context context, AttributeSet attrs) { super(context, attrs); mItems = new ArrayList<CanvasView.DrawableItem>(); mAction = ACTION.PEN; mDensityScale = getResources().getDisplayMetrics().density; } // ----------------------------------------------------------------------- // // Setters // // ----------------------------------------------------------------------- public void setAction(ACTION action) { if (mCurrentItem != null) saveCurrentModification(); mAction = action; invalidate(); } public void setColor(int color) { mColor = color; hideKeyboard(); } public void saveCurrentModification() { if (mCurrentItem instanceof Curve || !((Text) mCurrentItem).isEmpty()) mItems.add(mCurrentItem); mCurrentItem = null; } // ----------------------------------------------------------------------- // // Methods // // ----------------------------------------------------------------------- @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (DrawableItem item : mItems) item.draw(canvas, getMeasuredWidth(), getMeasuredHeight()); if (mCurrentItem != null) mCurrentItem.draw(canvas, getMeasuredWidth(), getMeasuredHeight()); } @Override public boolean onTouchEvent(MotionEvent event) { switch (mAction) { case PEN: onTouchPen(event); break; case TEXT: onTouchText(event); break; default: break; } return true; } private void onTouchPen(MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: mCurrentItem = new Curve(mColor); break; case MotionEvent.ACTION_MOVE: Curve currentItem = (Curve) mCurrentItem; currentItem.addPoint(event.getX(), event.getY()); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: saveCurrentModification(); break; default: } invalidate(); } private void onTouchText(MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: { if (mCurrentItem != null) saveCurrentModification(); mCurrentItem = new Text(new PointF(event.getX(), event.getY()), mDensityScale); showKeyboard(); } break; default: } } private void showKeyboard() { mEditText.setVisibility(View.VISIBLE); mEditText.setText(""); mEditText.requestFocus(); InputMethodManager inputMethodManager = (InputMethodManager) getContext() .getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.showSoftInput(mEditText, InputMethodManager.SHOW_IMPLICIT); } private void hideKeyboard() { mEditText.setVisibility(View.INVISIBLE); InputMethodManager imm = (InputMethodManager) getContext() .getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0); } @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putParcelable(EXTRA_SUPER_STATE, super.onSaveInstanceState()); bundle.putInt(EXTRA_COLOR, mColor); bundle.putSerializable(EXTRA_ACTION, mAction); bundle.putParcelableArrayList(EXTRA_MODIFICATIONS, mItems); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { Bundle bundle = (Bundle) state; setColor(bundle.getInt(EXTRA_COLOR)); setAction((ACTION) bundle.getSerializable(EXTRA_ACTION)); mItems = bundle.getParcelableArrayList(EXTRA_MODIFICATIONS); super.onRestoreInstanceState(bundle .getParcelable(EXTRA_SUPER_STATE)); return; } else super.onRestoreInstanceState(state); } public OnEditorActionListener getEditorActionListener() { return mEditorActionListener; } public TextWatcher getTextWatcher() { return mTextWatcher; } public void setTextProvider(EditText editText) { mEditText = editText; mEditText.setOnEditorActionListener(getEditorActionListener()); mEditText.addTextChangedListener(mTextWatcher); } public void clearSession() { mItems.clear(); mCurrentItem = null; hideKeyboard(); invalidate(); } // ----------------------------------------------------------------------- // // Listeners // // ----------------------------------------------------------------------- private OnEditorActionListener mEditorActionListener = new OnEditorActionListener() { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE) { saveCurrentModification(); hideKeyboard(); } return false; } }; private TextWatcher mTextWatcher = new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { if (mCurrentItem instanceof Text) { ((Text) mCurrentItem).setText(s.toString()); invalidate(); } } }; // ----------------------------------------------------------------------- // // Inner classes // // ----------------------------------------------------------------------- public static interface OnStartTextInputListener { public void onTextInputStarted(CanvasView view); } private static interface DrawableItem extends Parcelable { public void draw(Canvas canvas, float viewWidth, float viewHeight); } private static class Curve implements DrawableItem { // ----------------------------------------------------------------------- // // Fields // // ----------------------------------------------------------------------- private ArrayList<PointF> mPoints; private int mColor; private Paint mPaint; // ----------------------------------------------------------------------- // // Constructor // // ----------------------------------------------------------------------- public Curve(int color) { mPoints = new ArrayList<PointF>(); mColor = color; mPaint = new Paint(); mPaint.setColor(mColor); mPaint.setStrokeWidth(2); } private Curve(Parcel parcel) { mColor = parcel.readInt(); parcel.readList(mPoints, PointF.class.getClassLoader()); } // ----------------------------------------------------------------------- // // Methods // // ----------------------------------------------------------------------- @Override public void draw(Canvas canvas, float viewWidth, float viewHeight) { for (int i = 1; i < mPoints.size(); ++i) { PointF prev = mPoints.get(i - 1); PointF current = mPoints.get(i); canvas.drawLine(prev.x / viewWidth * canvas.getWidth(), prev.y / viewHeight * canvas.getHeight(), current.x / viewWidth * canvas.getWidth(), current.y / viewHeight * canvas.getHeight(), mPaint); } } public void addPoint(float x, float y) { mPoints.add(new PointF(x, y)); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mColor); dest.writeList(mPoints); } // ----------------------------------------------------------------------- // // Inner classes // // ----------------------------------------------------------------------- public static final Parcelable.Creator<Curve> CREATOR = new Parcelable.Creator<Curve>() { public Curve createFromParcel(Parcel in) { return new Curve(in); } public Curve[] newArray(int size) { return new Curve[size]; } }; } private static class Text implements DrawableItem { // ----------------------------------------------------------------------- // // Constatns // // ----------------------------------------------------------------------- private static final int FONT_SIZE = 14; private static final int PADDING = 4; private static final int BORDER_WIDTH = 2; private static final int BORDER_COLOR = Color.rgb(0, 0, 0); private static final int BOX_COLOR = Color.rgb(255, 255, 255); private static final int FONT_COLOR = Color.rgb(0, 0, 0); // ----------------------------------------------------------------------- // // Fields // // ----------------------------------------------------------------------- private Paint mBoxPaint; private Paint mBorderPaint; private Paint mTextPaint; private float mDensityScale; private PointF mPoint; private String mTextString = ""; // ----------------------------------------------------------------------- // // Constructor // // ----------------------------------------------------------------------- public Text(PointF point, float densityScale) { mPoint = point; mDensityScale = densityScale; mBoxPaint = new Paint(); mBoxPaint.setStyle(Style.FILL); mBoxPaint.setColor(BOX_COLOR); mBorderPaint = new Paint(); mBorderPaint.setStyle(Style.STROKE); mBorderPaint.setColor(BORDER_COLOR); mBorderPaint.setStrokeWidth(getBorderWidth()); mTextPaint = new Paint(); mTextPaint.setTextSize(getFontSize()); mTextPaint.setAntiAlias(true); mTextPaint.setTextAlign(Paint.Align.LEFT); mTextPaint.setColor(FONT_COLOR); } // ----------------------------------------------------------------------- // // Methods // // ----------------------------------------------------------------------- public void setText(String text) { mTextString = text; } public boolean isEmpty() { return Utils.isEmpty(mTextString); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { } private float getFontSize() { return FONT_SIZE * mDensityScale; } private float getPadding() { return PADDING * mDensityScale; } private float getBorderWidth() { return BORDER_WIDTH * mDensityScale; } private float getStringWidth(String string) { Rect bounds = new Rect(); mTextPaint.getTextBounds(string, 0, string.length(), bounds); return bounds.width(); } @Override public void draw(Canvas canvas, float viewWidth, float viewHeight) { ArrayList<String> labelList = new ArrayList<String>(); String[] lines = mTextString.split(" "); String prevLine = ""; float textHeight = (2 * getBorderWidth() + 2 * getPadding()) / viewHeight * canvas.getHeight(); float textWidth = 0; for (int i = 0; i < lines.length; ++i) { String string = lines[i]; String newline = prevLine.concat(" " + string).trim(); float prevLineWidth = (getStringWidth(prevLine) + 2 * getBorderWidth() + 2 * getPadding()) / viewWidth * canvas.getWidth(); float newLineWidth = (getStringWidth(newline) + 2 * getBorderWidth() + 2 * getPadding()) / viewWidth * canvas.getWidth(); float availableWidth = canvas.getWidth() - mPoint.x / viewWidth * canvas.getWidth() + 1; if (newLineWidth > availableWidth) { if (!Utils.isEmpty(prevLine)) { labelList.add(prevLine); textHeight += (getFontSize() + getPadding()) / viewHeight * canvas.getHeight(); if (prevLineWidth >= textWidth) textWidth = prevLineWidth; } prevLine = string; if (i == lines.length - 1) { prevLineWidth = (getStringWidth(prevLine) + 2 * getBorderWidth() + 2 * getPadding()) / viewWidth * canvas.getWidth(); labelList.add(prevLine); if (prevLineWidth > textWidth) textWidth = prevLineWidth; textHeight += getFontSize() / viewHeight * canvas.getHeight(); } } else if (i == lines.length - 1) { labelList.add(newline); if (newLineWidth > textWidth) textWidth = newLineWidth; textHeight += getFontSize() / viewHeight * canvas.getHeight(); } else { prevLine = newline; } } textHeight = Math.min(textHeight, canvas.getHeight() - mPoint.y / viewHeight * canvas.getHeight()); textWidth = Math.min(textWidth, canvas.getWidth() - mPoint.x / viewWidth * canvas.getWidth()); if (isEmpty()) { textWidth = (getPadding() * 2 + getBorderWidth() * 2) / viewWidth * canvas.getWidth(); } canvas.drawRect(mPoint.x / viewWidth * canvas.getWidth(), mPoint.y / viewHeight * canvas.getHeight(), mPoint.x / viewWidth * canvas.getWidth() + textWidth, mPoint.y / viewHeight * canvas.getHeight() + textHeight, mBoxPaint); mBorderPaint.setStrokeWidth(getBorderWidth() / viewWidth * canvas.getWidth()); canvas.drawRect(mPoint.x / viewWidth * canvas.getWidth(), mPoint.y / viewHeight * canvas.getHeight(), mPoint.x / viewWidth * canvas.getWidth() + textWidth, mPoint.y / viewHeight * canvas.getHeight() + textHeight, mBorderPaint); mBorderPaint.setStrokeWidth(getBorderWidth()); float offset = (getBorderWidth() + getPadding() + getFontSize()) / viewWidth * canvas.getWidth(); mTextPaint.setTextSize(getFontSize() / viewHeight * canvas.getHeight()); for (String string : labelList) { canvas.drawText(string, (mPoint.x + getBorderWidth()) / viewWidth * canvas.getWidth(), mPoint.y / viewHeight * canvas.getHeight() + offset, mTextPaint); offset += (getFontSize() + getPadding()) / viewHeight * canvas.getHeight(); } mTextPaint.setTextSize(getFontSize()); } } 
    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.