Android: ImageView and Bitmap

本文将详细解释如何在Android应用中从不同来源获取Bitmap,并通过设置Options属性来减少图片显示时的失真。包括从资源、字节数组、文件和使用BitmapRegionDecoder实例化部分图片的技巧。同时提供了解决图片转换为Bitmap时可能出现的失真的方法。

imageView.setImageBitmap(bitmap)


从res获得Bitmap:

Bitmap bitmap= BitmapFactory.decodeResource(getResources(), R.drawable.xxx);


从ByteArray获得Bitmap:

Bitmap bitmap= BitmapFactory.decodeByteArray(data, 0, data.length);


从文件获得Bitmap:

Bitmap bitmap= BitmapFactory.decodeFile(file_path);


从BitmapRegionDecoder获得部分图片Bitmap:

ParcelFileDescriptor fileDescriptor = ParcelFileDescriptor.open(
file, ParcelFileDescriptor.MODE_READ_ONLY);

BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(fileDescriptor.getFileDescriptor(), false);
Bitmap bitmap= decoder.decodeRegion(new Rect(0, 0, decoder.getWidth(), decoder.getHeight()), null);


图片转换为Bitmap显示在ImageView里面的失真问题:

添加Options属性

Options opts = new Options();

opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;

Bitmap bitmap= BitmapFactory.decodeFile(file_path, opts );

Bitmap bitmap= BitmapFactory.decodeByteArray(data, 0, data.length, opts );










<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:orientation="vertical" xmlns:app="http://schemas.android.com/apk/res-auto" tools:context=".PresetFragment"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="420dp" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" android:layout_marginTop="6dp"> <ImageView android:id="@+id/back" android:layout_width="24dp" android:layout_height="24dp" android:src="@drawable/auto_close" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toEndOf="@+id/back" android:text="Edit Preset" android:textSize="20sp" android:textColor="@color/black" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="@+id/back" android:layout_marginStart="5dp"/> <ImageView android:id="@+id/done" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" android:src="@drawable/auto_ok"/> <androidx.cardview.widget.CardView android:id="@+id/button_group" android:layout_width="250dp" android:layout_height="35dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/done" android:layout_marginTop="20dp" app:cardCornerRadius="17dp" android:backgroundTint="#F7F7F7"> <!-- 使用 LinearLayout 来水平排列两个按钮 --> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:baselineAligned="false"> <!-- 防止 baseline 对齐干扰 --> <com.google.android.material.button.MaterialButton android:id="@+id/white_light" android:layout_width="0dp" android:layout_weight="1" android:layout_height="35dp" android:backgroundTint="@color/blue" android:text="White Light" android:textColor="@color/white" android:gravity="center" android:paddingTop="0dp" android:paddingBottom="0dp" app:cornerRadius="17dp" android:textSize="12sp" /> <com.google.android.material.button.MaterialButton android:id="@+id/color_light" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:backgroundTint="@android:color/transparent" android:textColor="@color/gray_99999" android:text="Color Light" android:textSize="12sp" /> </LinearLayout> </androidx.cardview.widget.CardView> <TextView android:id="@+id/temperature_text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button_group" android:text="Color Temperature" android:textColor="@color/gray_99999" android:layout_marginTop="20dp"/> <com.example.tapobulb.view.ColorPickerView android:id="@+id/colorPickerView" android:layout_width="20dp" android:layout_height="20dp" android:src="@drawable/color_select" app:layout_constraintTop_toBottomOf="@+id/temperature_text" android:layout_marginTop="40dp" android:visibility="visible" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/> <ImageView android:id="@+id/color_select" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/color_select" app:layout_constraintTop_toBottomOf="@+id/temperature_text" android:layout_marginTop="38dp" android:visibility="visible" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/> <TextView android:id="@+id/color_temperature" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/button_group" android:text="2700K" android:textColor="@color/gray333" android:layout_marginTop="20dp"/> <TextView android:id="@+id/color_value" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/button_group" android:visibility="visible" android:text="xxxx" android:textColor="@color/gray333" android:layout_marginTop="20dp"/> <TextView android:id="@+id/warm" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/color_temperature" android:text="Warm" android:textColor="@color/gray_99999" android:textSize="14sp" android:layout_marginTop="24dp"/> <com.example.tapobulb.view.DashedLineView android:id="@+id/line1" android:layout_width="wrap_content" android:layout_height="9dp" android:background="@drawable/dashed_line" app:layout_constraintStart_toEndOf="@id/warm" app:layout_constraintTop_toBottomOf="@+id/color_temperature" android:layout_marginStart="20dp" android:layout_marginTop="26dp"/> <TextView android:id="@+id/recommend" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/warm" android:text="Recommend" android:textColor="@color/gray_99999" android:layout_marginTop="46dp"/> <com.example.tapobulb.view.DashedLineView android:id="@+id/line2" android:layout_width="wrap_content" android:layout_height="9dp" android:background="@drawable/dashed_line" app:layout_constraintStart_toEndOf="@id/recommend" app:layout_constraintTop_toBottomOf="@+id/warm" android:layout_marginStart="20dp" android:layout_marginTop="48dp"/> <TextView android:id="@+id/white" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/recommend" android:text="White" android:textColor="@color/gray_99999" android:layout_marginTop="46dp"/> <com.example.tapobulb.view.DashedLineView android:id="@+id/line3" android:layout_width="wrap_content" android:layout_height="9dp" android:background="@drawable/dashed_line" app:layout_constraintStart_toEndOf="@id/white" app:layout_constraintTop_toBottomOf="@+id/recommend" android:layout_marginStart="20dp" android:layout_marginTop="48dp"/> <TextView android:id="@+id/daylight" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/white" android:text="Daylight" android:textColor="@color/gray_99999" android:layout_marginTop="46dp"/> <com.example.tapobulb.view.DashedLineView android:id="@+id/line4" android:layout_width="wrap_content" android:layout_height="9dp" android:background="@drawable/dashed_line" app:layout_constraintStart_toEndOf="@id/daylight" app:layout_constraintTop_toBottomOf="@+id/white" android:layout_marginStart="20dp" android:layout_marginTop="48dp"/> <TextView android:id="@+id/cool" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/daylight" android:text="Cool" android:textColor="@color/gray_99999" android:layout_marginTop="46dp"/> <com.example.tapobulb.view.DashedLineView android:id="@+id/line5" android:layout_width="wrap_content" android:layout_height="9dp" android:background="@drawable/dashed_line" app:layout_constraintStart_toEndOf="@id/cool" app:layout_constraintTop_toBottomOf="@+id/daylight" android:layout_marginStart="20dp" android:layout_marginTop="48dp"/> <ImageView android:id="@+id/color_bar" android:layout_width="60dp" android:layout_height="238dp" android:src="@drawable/color_bar" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@id/color_temperature" android:layout_marginTop="46dp"/> <FrameLayout android:id="@+id/temperature_select" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/temperature_rectangle" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@id/color_temperature" android:layout_marginTop="50dp"/> <View android:layout_width="match_parent" app:layout_constraintTop_toBottomOf="@+id/color_temperature" android:layout_marginTop="100dp" android:layout_height="10dp"/> <androidx.constraintlayout.widget.Group android:id="@+id/white_group" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" app:constraint_referenced_ids="color_bar,color_temperature,temperature_select,temperature_select,warm,line1,recommend,line2,white,line3,daylight,line4,cool,line5"/> </androidx.constraintlayout.widget.ConstraintLayout> <View android:layout_width="match_parent" android:layout_height="10dp" android:background="@color/bg_gray" android:layout_marginTop="20dp"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/daylight" android:text="Light" android:textSize="18sp" android:layout_marginStart="16dp" android:textColor="@color/gray_99999" android:layout_weight="1" android:layout_marginTop="46dp"/> <TextView android:id="@+id/light_percent" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/daylight" android:text="64%" android:textSize="18sp" android:layout_marginStart="16dp" android:textColor="@color/gray333" android:layout_marginEnd="16dp" android:layout_marginTop="46dp"/> </LinearLayout> <SeekBar android:id="@+id/seekBar" android:layout_marginTop="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" android:progressDrawable="@drawable/custom_seekbar_progress" android:thumb="@drawable/seekbar_icon_resized" android:splitTrack="false" android:minHeight="4dp" android:maxHeight="4dp" android:max="100" android:progress="50" /> <View android:layout_width="match_parent" android:layout_height="30dp"/> </LinearLayout>package com.example.tapobulb.view import android.content.Context import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Color import android.graphics.DashPathEffect import android.graphics.Matrix import android.graphics.Paint import android.graphics.Rect import android.graphics.drawable.BitmapDrawable import android.util.AttributeSet import android.view.MotionEvent import androidx.appcompat.widget.AppCompatImageView import kotlin.math.abs /** * @Author: admin * @CreateDate: 2025/8/25 9:30 * @Description: */ class ColorPickerView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : AppCompatImageView(context, attrs, defStyleAttr) { private var selectedColor: Int = Color.TRANSPARENT private var showCircle = false private var clickX = 0f private var clickY = 0f // 拖动选取相关 private var isDragging = false private var dragStartX = 0f private var dragStartY = 0f private var dragEndX = 0f private var dragEndY = 0f // 放大镜相关 private val magnifierRadius = 100f private val magnifierBitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888) private val magnifierCanvas = Canvas(magnifierBitmap) private val magnifierPaint = Paint() private val matrix = Matrix() private var showMagnifier = false private val paint = Paint() private val outerRadius = 30f private val innerRadius = 15f // 回调 var colorSelectedListener: ((Int) -> Unit)? = null var colorRegionSelectedListener: ((IntArray) -> Unit)? = null override fun onTouchEvent(event: MotionEvent): Boolean { val bitmap = (drawable as? BitmapDrawable)?.bitmap ?: return super.onTouchEvent(event) when (event.action) { MotionEvent.ACTION_DOWN -> { isDragging = true dragStartX = event.x dragStartY = event.y clickX = event.x clickY = event.y showMagnifier = true invalidate() } MotionEvent.ACTION_MOVE -> { if (isDragging) { dragEndX = event.x dragEndY = event.y invalidate() } } MotionEvent.ACTION_UP -> { isDragging = false showMagnifier = false // 单点取色 if (dragStartX == event.x && dragStartY == event.y) { if (clickX.toInt() in 0 until bitmap.width && clickY.toInt() in 0 until bitmap.height) { selectedColor = bitmap.getPixel(clickX.toInt(), clickY.toInt()) showCircle = true invalidate() colorSelectedListener?.invoke(selectedColor) } } else { // 区域取色 val startX = dragStartX.toInt().coerceIn(0, bitmap.width) val endX = dragEndX.toInt().coerceIn(0, bitmap.width) val startY = dragStartY.toInt().coerceIn(0, bitmap.height) val endY = dragEndY.toInt().coerceIn(0, bitmap.height) val width = abs(endX - startX) val height = abs(endY - startY) val pixels = IntArray(width * height) bitmap.getPixels(pixels, 0, width, startX, startY, width, height) colorRegionSelectedListener?.invoke(pixels) } } } return true } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) if (showMagnifier) { drawMagnifier(canvas) } if (showCircle) { // 绘制选中圆圈 paint.color = selectedColor paint.style = Paint.Style.STROKE paint.strokeWidth = 6f canvas.drawCircle(clickX, clickY, outerRadius, paint) paint.color = Color.WHITE paint.style = Paint.Style.FILL canvas.drawCircle(clickX, clickY, innerRadius, paint) } if (isDragging) { // 绘制拖动框 paint.apply { color = Color.BLACK style = Paint.Style.STROKE strokeWidth = 4f pathEffect = DashPathEffect(floatArrayOf(10f, 10f), 0f) } canvas.drawRect(dragStartX, dragStartY, dragEndX, dragEndY, paint) } } private fun drawMagnifier(canvas: Canvas) { val bitmap = (drawable as? BitmapDrawable)?.bitmap ?: return val centerX = clickX.toInt().coerceIn(0, bitmap.width) val centerY = clickY.toInt().coerceIn(0, bitmap.height) val size = 40 val srcRect = Rect(centerX - size / 2, centerY - size / 2, centerX + size / 2, centerY + size / 2) val dstRect = Rect(0, 0, 200, 200) magnifierCanvas.drawBitmap(bitmap, srcRect, dstRect, magnifierPaint) matrix.reset() matrix.postScale(3f, 3f, 100f, 100f) matrix.postTranslate(clickX - 150, clickY - 150) canvas.drawBitmap(magnifierBitmap, matrix, magnifierPaint) canvas.drawCircle(clickX, clickY, magnifierRadius, magnifierPaint.apply { style = Paint.Style.STROKE strokeWidth = 4f color = Color.RED }) } } 这是我的布局和我的view,但是有个问题啊,你这个自定义view根本没有展现在页面上啊
08-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值