OneSearch에 처음 플립뷰를 이용해서 이미지 뷰어를 만들었을 때.. 핀치 줌을 사용해서 이미지를 확대/축소를 하고 싶었는데..
간단하게 처리가 되지 않았서 그냥 다음에 하지머..하고 넘어간적이 있었다.
얼마전, 다른 앱을 작업하다가 핀치 줌을 이용해야 하는 경우가 다시 발생해서 떡 본김에 제사 지낸다고, 그냥 만들었다. 음 물론 시간은
4-5시간 정도 걸린 것 같다.
x:Class="FlipViewSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:FlipViewSample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:commons="using:FlipViewSample.Commons"
mc:Ignorable="d">
<Page.Resources>
<DataTemplate
x:Key="DataTemplate1">
<ScrollViewer x:Name="scrollViewer"
ZoomMode="Enabled"
HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch">
<Image
Stretch="None" Source="{Binding PhotoUri}" Tag="{Binding
PhotoUri}">
<interactivity:Interaction.Behaviors>
<commons:ImageBehavior ZoomScrollViewer="{Binding
ElementName=scrollViewer}"/>
</interactivity:Interaction.Behaviors>
</Image>
</ScrollViewer>
</DataTemplate>
</Page.Resources>
<Page.DataContext>
<local:MainPageViewModel/>
</Page.DataContext>
<Grid Background="{ThemeResource
ApplicationPageBackgroundThemeBrush}">
<FlipView
x:Name="flipView" ItemsSource="{Binding PhotoList}"
ItemTemplate="{StaticResource DataTemplate1}"
ManipulationMode="TranslateX"/>
</Grid>
</Page>
FlipView에 ManipulationMode="TranslateX"를 지정하는 것이 중요하다. FilpView는 가로 방향의 제스처에만
반응하도록 만들어야 한다.
ScrollViewer에는 위에 굵은 글씨들의 내용을 꼭 추가해 줘야한다.
}
{
// Using a DependencyProperty as the backing store
for ScrollViewer. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ScrollViewerProperty =
DependencyProperty.Register("ZoomScrollViewer", typeof (ScrollViewer), typeof
(ImageBehavior),
new PropertyMetadata(null));
/// <summary>
/// 중복실행 방지
///
</summary>
private bool _isWork;
/// <summary>
/// 중복실행 방지
///
</summary>
private readonly object _lock = new object();
public ScrollViewer ZoomScrollViewer
{
get
{ return (ScrollViewer) GetValue(ScrollViewerProperty); }
set {
SetValue(ScrollViewerProperty, value); }
}
public void Attach(DependencyObject associatedObject)
{
if (!(associatedObject is Image)) return;
var im
= (Image) associatedObject;
AssociatedObject = im;
im.ImageOpened += Im_ImageOpened;
if (ZoomScrollViewer == null) return;
ZoomScrollViewer.SizeChanged += ZoomScrollViewer_SizeChanged;
}
public void Detach()
{
var im = (Image)
AssociatedObject;
im.ImageOpened -=
Im_ImageOpened;
if (ZoomScrollViewer == null)
return;
ZoomScrollViewer.SizeChanged +=
ZoomScrollViewer_SizeChanged;
}
public DependencyObject AssociatedObject { get; private set; }
private void ZoomScrollViewer_SizeChanged(object sender,
SizeChangedEventArgs e)
{
SizeChanged();
}
/// <summary>
/// 이미지가 열렸을 때 기본 크기 변경
/// </summary>
/// <param
name="sender"></param>
/// <param
name="e"></param>
private void Im_ImageOpened(object sender,
RoutedEventArgs e)
{
SizeChanged();
}
private void SizeChanged()
{
lock
(_lock)
{
if (_isWork)
return;
_isWork = true;
}
if
(ZoomScrollViewer == null) return;
var im = (Image)
AssociatedObject;
//이미지 사이즈에 맞춰서 줌팩터 조정
var w1 =
Convert.ToSingle(ZoomScrollViewer.ViewportWidth/(im.ActualWidth +
40.0f));
var h1 =
Convert.ToSingle(ZoomScrollViewer.ViewportHeight/(im.ActualHeight +
40.0f));
Debug.WriteLine("ZoomFactor w1={0}, h1={1}", w1,
h1);
var zoomFactor = Math.Min(w1,
h1);
if (Math.Abs(ZoomScrollViewer.ZoomFactor -
zoomFactor) > 0)
{
ZoomScrollViewer.ChangeView(0, 0,
Math.Min(w1, h1));
}
_isWork = false;
}
}
전체 소스는 첨부 파일을 참고한다.
4. 이미지를 앱에서 표시할 때 가장 좋은 선택은 이미지의 경로를 문자열 만들고, 그 것을 Image.Source에 바인딩을 하는 것이
좋다.