feat: varsayilan fill modu, zoom merkezleme duzeltildi, alt bilgi cubugu
Some checks failed
Build Windows / build-windows (push) Has been cancelled

This commit is contained in:
Alhan
2026-07-22 05:41:32 +03:00
parent c5679f457d
commit 5f9382ef61
4 changed files with 95 additions and 51 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -1,6 +1,7 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import '../services/image_manager.dart';
class ImageCanvas extends StatefulWidget {
final String filePath;
@@ -14,7 +15,7 @@ class ImageCanvas extends StatefulWidget {
class _ImageCanvasState extends State<ImageCanvas> {
late TransformationController _controller;
double _currentScale = 1.0;
bool _isFilled = false; // false=fit, true=cover
bool _isFilled = true; // varsayılan: ekranı doldur
@override
void initState() {
@@ -34,7 +35,7 @@ class _ImageCanvasState extends State<ImageCanvas> {
void _resetView() {
_controller.value = Matrix4.identity();
_currentScale = 1.0;
_isFilled = false;
_isFilled = true; // yeni resimde fill moduna dön
}
void _onTransformChanged() {
@@ -67,6 +68,7 @@ class _ImageCanvasState extends State<ImageCanvas> {
final actualScale = newScale / _currentScale;
// Fare altındaki child-space noktayı hesapla
final matrix = _controller.value;
final tx = matrix.getTranslation().x;
final ty = matrix.getTranslation().y;
@@ -74,18 +76,28 @@ class _ImageCanvasState extends State<ImageCanvas> {
final childX = (localPosition.dx - tx) / _currentScale;
final childY = (localPosition.dy - ty) / _currentScale;
final newMatrix = Matrix4.identity()
// controller * zoomAroundPoint sırasıyla uygula
final newMatrix = Matrix4.copy(_controller.value)
// ignore: deprecated_member_use
..translate(childX, childY)
// ignore: deprecated_member_use
..scale(actualScale)
// ignore: deprecated_member_use
..translate(-childX, -childY)
..multiply(_controller.value);
..translate(-childX, -childY);
_controller.value = newMatrix;
}
String _zoomPercent() {
return '${(_currentScale * 100).round()}%';
}
String _imageInfo() {
final mgr = ImageManager.instance;
if (mgr.images.isEmpty) return '';
return '${mgr.currentIndex + 1} / ${mgr.imageCount}';
}
@override
void dispose() {
_controller.removeListener(_onTransformChanged);
@@ -105,54 +117,86 @@ class _ImageCanvasState extends State<ImageCanvas> {
},
child: GestureDetector(
onDoubleTap: _handleDoubleTap,
child: InteractiveViewer(
transformationController: _controller,
boundaryMargin: const EdgeInsets.all(double.infinity),
minScale: 0.1,
maxScale: 10.0,
panEnabled: true,
scaleEnabled: false,
child: _isFilled
? SizedBox.expand(
child: Image.file(
File(widget.filePath),
fit: BoxFit.cover,
filterQuality: FilterQuality.high,
errorBuilder: (context, error, stackTrace) {
return const Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.broken_image, size: 48, color: Colors.white38),
SizedBox(height: 8),
Text('Resim yüklenemedi',
style: TextStyle(color: Colors.white38)),
],
child: Stack(
children: [
InteractiveViewer(
transformationController: _controller,
boundaryMargin: const EdgeInsets.all(double.infinity),
minScale: 0.1,
maxScale: 10.0,
panEnabled: true,
scaleEnabled: false,
child: _isFilled
? SizedBox.expand(
child: Image.file(
File(widget.filePath),
fit: BoxFit.cover,
filterQuality: FilterQuality.high,
errorBuilder: (context, error, stackTrace) {
return const Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.broken_image, size: 48, color: Colors.white38),
SizedBox(height: 8),
Text('Resim yüklenemedi',
style: TextStyle(color: Colors.white38)),
],
),
);
},
),
)
: Center(
child: Image.file(
File(widget.filePath),
fit: BoxFit.contain,
filterQuality: FilterQuality.high,
errorBuilder: (context, error, stackTrace) {
return const Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.broken_image, size: 48, color: Colors.white38),
SizedBox(height: 8),
Text('Resim yüklenemedi',
style: TextStyle(color: Colors.white38)),
],
),
);
},
),
),
),
// Alt bilgi çubuğu
Positioned(
bottom: 4,
left: 0,
right: 0,
child: Center(
child: ListenableBuilder(
listenable: _controller,
builder: (context, _) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 3),
decoration: BoxDecoration(
color: Colors.black54,
borderRadius: BorderRadius.circular(6),
),
child: Text(
'${_imageInfo()} | ${_zoomPercent()}',
style: const TextStyle(
color: Colors.white70,
fontSize: 12,
fontFamily: 'monospace',
),
);
},
),
)
: Center(
child: Image.file(
File(widget.filePath),
fit: BoxFit.contain,
filterQuality: FilterQuality.high,
errorBuilder: (context, error, stackTrace) {
return const Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.broken_image, size: 48, color: Colors.white38),
SizedBox(height: 8),
Text('Resim yüklenemedi',
style: TextStyle(color: Colors.white38)),
],
),
);
},
),
),
);
},
),
),
),
],
),
),
);

Binary file not shown.