我正在尝试在xamarin跨平台应用程序中实现类似的缩放功能,例如Instagram移动应用程序提要屏幕。
实际上,我想在ImageView
单元格内的ListView
上添加捏合手势,如果用户捏合图像,则应该在ListView
上进行放大。用户松开捏后,应自动将其调整为原始大小并适合单元格。
帮助我并提供解决方案。
以下示例代码正常工作,但在单元格内部进行了缩放,这不像Instagram的缩放重叠/叠加效果。
XAML代码
<ListView x:Name="listView" ItemSelected="PlayerList_OnItemSelected" HasUnevenRows="false" RowHeight="300" BackgroundColor="#F6F3F6"
RelativeLayout.XConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Width, Factor=0}"
RelativeLayout.YConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Height, Factor=.09}"
RelativeLayout.HeightConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Height, Factor=.91}"
RelativeLayout.WidthConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Width, Factor=1}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<Frame Margin="5" Padding="5" OutlineColor="White" HasShadow="true">
<RelativeLayout >
<Label Font="Bold,20" Text="{Binding name}" TextColor="Black"
RelativeLayout.YConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Height,
Factor=.0}"
RelativeLayout.XConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Width,
Factor=.02}"
RelativeLayout.WidthConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Width,
Factor=.9}"/>
<local:PinchToZoomContainer RelativeLayout.WidthConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Width,
Factor=1}"
RelativeLayout.XConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Width,
Factor=0}"
RelativeLayout.YConstraint="{ConstraintExpression
Type=RelativeToParent,
Factor=.15,
Property=Height}">
<local:PinchToZoomContainer.Content>
<Image x:Name="imgBg" HeightRequest="180" Aspect="AspectFill" BackgroundColor="#F0F3F4" Margin="1,1,1,-1" Source="{Binding thumbnail, Converter={StaticResource GetFeedImage}}" />
</local:PinchToZoomContainer.Content>
</local:PinchToZoomContainer>
<Label FontSize="10" TextColor="#96AAC0" HorizontalTextAlignment="Center" HeightRequest="40" Text="{Binding posted_at}"
RelativeLayout.YConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Height,
Factor=.02}"
RelativeLayout.XConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Width,
Factor=.81}"
RelativeLayout.WidthConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Width,
Factor=.2}"/>
<Label FontSize="12" TextColor="#5B636E" HorizontalTextAlignment="Start" Text="{Binding description}"
RelativeLayout.YConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Height,
Factor=.87}"
RelativeLayout.XConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Width,
Factor=.01}"
RelativeLayout.WidthConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Width,
Factor=.98}"
RelativeLayout.HeightConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Height,
Factor=0,
Constant=30}"/>
</RelativeLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Zoom容器类
public class PinchToZoomContainer : ContentView
{
double currentScale = 1;
double startScale = 1;
double xOffset = 0;
double yOffset = 0;
public PinchToZoomContainer ()
{
var pinchGesture = new PinchGestureRecognizer ();
pinchGesture.PinchUpdated += OnPinchUpdated;
GestureRecognizers.Add (pinchGesture);
}
void OnPinchUpdated (object sender, PinchGestureUpdatedEventArgs e)
{
if (e.Status == GestureStatus.Started) {
// Store the current scale factor applied to the wrapped user interface element,
// and zero the components for the center point of the translate transform.
startScale = Content.Scale;
Content.AnchorX = 0;
Content.AnchorY = 0;
}
if (e.Status == GestureStatus.Running) {
// Calculate the scale factor to be applied.
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max (1, currentScale);
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the X pixel coordinate.
double renderedX = Content.X + xOffset;
double deltaX = renderedX / Width;
double deltaWidth = Width / (Content.Width * startScale);
double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the Y pixel coordinate.
double renderedY = Content.Y + yOffset;
double deltaY = renderedY / Height;
double deltaHeight = Height / (Content.Height * startScale);
double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
// Calculate the transformed element pixel coordinates.
double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);
// Apply translation based on the change in origin.
Content.TranslationX = targetX.Clamp (-Content.Width * (currentScale - 1), 0);
Content.TranslationY = targetY.Clamp (-Content.Height * (currentScale - 1), 0);
// Apply scale factor
Content.Scale = currentScale;
}
if (e.Status == GestureStatus.Completed) {
// Store the translation delta's of the wrapped user interface element.
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
}
}
}