Я работаю над созданием пользовательского ImageView, который обрезает изображение в форме шестиугольника и добавит границу. Мне было интересно, правильный ли мой подход или если я делаю это неправильно. Есть куча пользовательских библиотек, которые уже делают это, но ни один из них не имеет форму, которую я ищу. Это, как говорится, больше вопрос о лучшей практике.Форма пользовательского изображения для Android
Вы можете увидеть полный класс в этом gist, но главный вопрос заключается в том, что это лучший подход. Мне кажется, что это неправильно, отчасти из-за некоторых волшебных чисел, что означает, что он может быть испорчен на некоторых устройствах.
Вот мясо код:
@Override protected void onDraw(Canvas canvas) { Drawable drawable = getDrawable(); if (drawable == null || getWidth() == 0 || getHeight() == 0) { return; } Bitmap b = ((BitmapDrawable) drawable).getBitmap(); Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true); int dimensionPixelSize = getResources().getDimensionPixelSize(R.dimen.width); // (width and height of ImageView) Bitmap drawnBitmap = drawCanvas(bitmap, dimensionPixelSize); canvas.drawBitmap(drawnBitmap, 0, 0, null); } private Bitmap drawCanvas(Bitmap recycledBitmap, int width) { final Bitmap bitmap = verifyRecycledBitmap(recycledBitmap, width); final Bitmap output = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(output); final Rect rect = new Rect(0, 0, width, width); final int offset = (int) (width/(double) 2 * Math.tan(30 * Math.PI/(double) 180)); // (width/2) * tan(30deg) final int length = width - (2 * offset); final Path path = new Path(); path.moveTo(width/2, 0); // top path.lineTo(0, offset); // left top path.lineTo(0, offset + length); // left bottom path.lineTo(width/2, width); // bottom path.lineTo(width, offset + length); // right bottom path.lineTo(width, offset); // right top path.close(); //back to top Paint paint = new Paint(); paint.setStrokeWidth(4); canvas.drawARGB(0, 0, 0, 0); canvas.drawPath(path, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); // draws the bitmap for the image paint.setColor(Color.parseColor("white")); paint.setStrokeWidth(4); paint.setDither(true); paint.setStyle(Paint.Style.STROKE); paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeCap(Paint.Cap.ROUND); paint.setPathEffect(new CornerPathEffect(10)); paint.setAntiAlias(true); // draws the border canvas.drawPath(path, paint); return output; }
Я смотрел на какой-то IOS код и они могут применить реальное изображение в качестве маски, чтобы достичь этого результата. Есть ли в Android в любом случае сделать что-то подобное?
Возможно, [это] (https://github.com/siyamed/android-shape-imageview) соответствует вашим потребностям? –
Я бы сказал, сделайте свою ширину хода, смещение + X & CornerPathEffect конвертируйте в пиксели из dp (используя TypedValue), но кроме этого, он выглядит довольно хорошо.30 градусов - это хорошо, так как 30 градусов - 30 градусов на любом устройстве (или где-нибудь в юниверсе, если на то пошло) –
@GilMoshayof спасибо, я думаю, я смотрел на какой-то код iOS, и они могут применять svg как слой поверх их изображения. Я надеялся, что в Android мне чего-то не хватает, что позволит мне это сделать. – trev9065