Microsoft-ui-xaml: より柔軟なScrollViewer

作成日 2018年12月19日  ·  61コメント  ·  ソース: microsoft/microsoft-ui-xaml

これは、新機能またはAPI提案のテンプレートです。 たとえば、これを使用して、既存のタイプに新しいAPIを提案したり、新しいUIコントロールのアイデアを提案したりできます。 すべての詳細がわからなくても問題ありません。要約と理論的根拠から始めることができます。 次のリンクでは、WinUI機能/ APIプロポーザルプロセスについて説明しています。https://github.com/Microsoft/microsoft-ui-xaml-specs/blob/master/docs/feature_proposal_process.md機能またはAPIプロポーザルのタイトルを追加します。 短く説明してください

提案:ScrollViewer

概要

tl:dr; 柔軟でありながら使いやすいXAMLのスクロールおよびズーム制御を提供します。これは、Win10のダウンレベルリリースを対象とする場合でも利用できます。

ScrollViewerコントロールは、アプリケーションとコントロール(プラットフォームと非プラットフォームの両方)にとって基本的なスクロールが非常に重要であるため、どのUIでも重要な役割を果たします。 このコントロールは、デフォルトのポリシーとUX(たとえば、意識的なスクロールバー、フォーカス/キーボードの相互作用、アクセシビリティ、デフォルトのスクロールアニメーションなど)とともに、パンとズームの機能を提供します。 また、日常のアプリシナリオを簡単にすることから、スクロールベースのコントロールの主要コンポーネントになり、非常に高度なユースケースにサービスを提供できるように、十分な柔軟性が必要です。 現在の制御では、このレベルの柔軟性は提供されません。

理論的根拠

すべての開発者とユーザーのために、この機能をWinUIに追加する必要がある理由を説明してください。 該当する場合は、現在のWinUIロードマップと優先順位にどのように対応するかを説明することもできます:https://github.com/Microsoft/microsoft-ui-xaml-specs/blob/master/docs/roadmap.md

コアプラットフォームのパブリックAPIに階層化された方法で、ScrollViewerコントロールをリポジトリに導入することは、次のような重要な足がかりになります。

  1. より多くのコントロールをリポジトリに持ち上げることができます(俊敏性の向上)。
  2. 開発者に、低レベルのプラットフォーム機能の柔軟性と高レベルのフレームワークサービス(アクセシビリティなど)の利点を組み合わせた使いやすいコントロールを提供します。
  3. XAMLの新しいスクロール関連機能を有効にして、以前のバージョンのWin10でライトアップします。

既存のコントロールは、 DirectManipulation APIに基づいてWin8で作成されました

既存のScrollViewerコントロールをそのまま抽出することは、初心者ではありません。 代わりに、コントロールは、 InteractionTrackerの新しい(そしてすでに利用可能な)機能に基づいて、ほぼ同一のAPIサーフェスを使用して再実装する必要があります。

高レベルの計画

_Windows_.UI.Xaml.Controls名前空間にある既存のScrollViewerは、(重大なバグを修正する以外は)変更されません。

新しいScrollViewerは、_Microsoft_.UI.Xaml.Controls名前空間に存在します。 APIは_Windows_バージョンとほとんど同じです。 明確なメリットがある場合は、コントロールのAPIに的を絞った調整を行います(一般的なシナリオの簡素化、新しい機能の導入など)。

新しいScrollViewerと組み合わせて、Microsoft.UI.Xaml.Controls._Primitives_名前空間に存在する新しいタイプのScrollerを導入します。 Scrollerは、 InteractionTrackerの機能に基づいて、XAMLでスクロールおよびズームするためのコア機能を提供します。

両方のコントロールの最初の目標は、次の公式リリースの一部となる品質を出荷するためのコア機能を取得することです。 ファイナライズされていないAPIは「プレビュー」のままで、プレリリースパッケージの一部としてのみ利用できます。

--------------------アイデアや提案を提出する場合、以下のセクションはオプションです。 マスターするPRを受け入れる前にすべてのセクションが必要ですが、ディスカッションを開始する必要はありません。 ----------------------

機能要件


| #| 機能| | 優先度|
|:-:|:-|-|:-:|
| 1 | 既存のScrollViewerと一致するデフォルトのUXを使用して、_非封印_のパンおよびズームコントロールを提供します。 || しなければならない|
| 2 | プラットフォームでサポートされているパブリックAPIのみに依存することにより、プラットフォームの機能を示します。 || しなければならない|
| 3 | フレームワークレベルのXAMLサービスと統合します。
例えば:
-システムフォーカスを正しくレンダリングします
-フォーカスされた要素を自動的に表示します(キーボード、ゲームパッド、スクリーンリーダー)
-効果的なビューポートの変更に参加し
-スクロールアンカーをサポート|| しなければならない|
| 4 | 入力駆動型アニメーションを実行できる|| しなければならない|
| 5 | リポジトリにすでに存在する既存のスクロール依存コントロール(つまり、ParallaxView、RefreshContainer、SwipeControl)と組み合わせて使用​​できます。 || しなければならない|
| 6 | 慣性ビューの変更(つまり、カスタムアニメーションのスクロールまたはズーム)の曲線を制御できます。 || しなければならない|
| 7 | 絶対オフセットまたは相対オフセットに基づいてビューを変更できます(たとえば、関心のあるポイントまでスクロールします)|| しなければならない|
| 8 | インパルス/追加速度に基づいてビューを変更できます(たとえば、ドラッグアンドドロップ中の自動スムーズスクロールまたはマウス選択長方形による複数選択)|| しなければならない|
| 9 | オーバーパンをどれだけ検出できるか|| しなければならない|
| 10 | スクロール状態の変化を観察し、それに反応することができる|| しなければならない|
| 11 | スナップポイントのスクロールとズームのサポート。 || すべき|
| 12 | カスタムの「スクロールバー」コントロールを使用してスクロールを駆動できます(写真のタイムラインスクラバーなど)。 || すべき|
| 13 | 特定の入力の種類を無視するようにコントロールを簡単に構成できます(たとえば、タッチまたはペンに応答しますが、マウスホイールの入力は無視します)。 || すべき|
| 14 | スクロール位置を保存および復元できる(仮想化リストなど)|| すべき|
| 15 | スティッキーヘッダー/要素のサポート。 || すべき|
| 16 | ユーザーがすばやく連続してジェスチャーを繰り返す場合の高速スクロールのサポート。 || すべき|
| 17 | マウスの中クリックとスクロールをサポートするデフォルトのUXを提供します。 |mousewheel panning | すべき|
| 18 | マウスを介してクリックしてパンするモードをサポートします(PDFビューア内でコンテンツを移動するなど)。 |mouse hand cursor for panning | すべき|
| 19 | カスタムコントロールを使用してズームを駆動できます(ズームスライダーなど)。 || すべき|
| 20 | スクロール可能領域に含まれるコンテンツを印刷できます。 || すべき|
| 21 | 回転ジェスチャをサポートします。 || できた|
| 22 | 2つ以上の領域をちらつきやジャンクのないスクロールで同期できます(テキスト差分シナリオなど)。 || できた|
| 23 | 入力によるビューの変更に合わせてアニメーションカーブをカスタマイズできます(つまり、重力ウェルなどの指を下に向ける動作を定義します)。 || できた|
| 24 | 上または下へのスクロールジェスチャをサポートします。 || できた|
| 25 | オーバーパンを無効にすることができます。 || できた|
| 26 | UIElementのManipulationModeプロパティに基づいて、ScrollViewer内のコンテンツを選択的に操作できます。 || できた|
| 27 | 慣性をオフにしたり、慣性から跳ね返ったりすることができます。 || できた|
| 28 | コンテンツのクリッピングを無効にすることができます(つまり、 CanContentRenderOutsideBounds )。 || できた|
| 29 | ビュー変更の終了時に完了理由を判別できます。 || できた|

用語

  • _Overpan_は、ユーザーがコンテンツのサイズを超えてパンまたはズームしようとし、弾性/ラバーバンド効果が発生した場合です。
  • _Railing_は、最初のジェスチャの方向に基づいて、スクローラーが動きを「優先」軸に自動的にロックする場合です。
  • _Chaining_は、別の内部にネストされたスクロール可能なサーフェスがあり、内側のスクロール動作がその範囲に達すると、外側のサーフェスで続行するようにプロモートされる場合です。
  • _スナップポイント_は、慣性スクロールの終了時にビューポートが
  • _スクロールアンカー_は、表示されているコンテンツの相対位置を維持するためにビューポートが自動的にシフトする場所です。 レイアウトによるコンテンツの位置やサイズの突然の変化による影響をユーザーが防ぐことができます(つまり、ユーザーが記事を読んでいて、しばらくすると、記事の上部にある画像/広告が最終的に読み込まれるため、すべてがジャンプダウンします) 。 スクロールアンカーは、可変サイズのコンテンツを処理する場合のUI仮想化に必要です。
  • _Gravity wells_は、ユーザーがコンテンツを操作している間(つまり、ユーザーの指が下にあるとき)のスクロール動作に影響を与えるスクロール可能なコンテンツ内の場所です。 たとえば、重力ウェルを使用して、ユーザーがアクティブにパンまたはズームすると、動きが遅くなったり速くなったりするように見えるスクロールの知覚摩擦を変更できます。

使用例

この機能の使用方法を示す例を1つ以上含めてください。 役立つ場合は、コード例やスクリーンショットを含めることができます

序文

デフォルトでは、コンテンツのサイズがビューポートよりも大きい場合、ScrollViewerはコンテンツのパンをサポートします。 コンテンツのサイズは、XAMLのレイアウトシステムによって決定されます。

ここでの例は、現在のScrollViewerと新しいScrollViewerの主なAPIの違いを強調することを目的としています。

垂直スクロール(違いなし)

コンテンツの幅は、ビューポートと同じになるように自動的に制限されます。 高さには制約がありません。 ビューポートの高さを超える場合、ユーザーはさまざまな入力モダリティを介してパンできます。

<ScrollViewer Width="500" Height="400">
    <ItemsRepeater ItemsSource="{x:Bind ViewModel.Items}" ItemTemplate="{StaticResource MyTemplate}"/>
</ScrollViewer>

水平スクロール

これは、以前はHorizo​​ntalScrollBarVisibilityを変更する必要があった既存のScrollViewerからの意図的な逸脱です。 それは多くの開発者を混乱させました。

<ScrollViewer Width="500" Height="400" ContentOrientation="Horizontal">
    <StackPanel Orientation="Horizontal">
        <!-- ... -->
    </StackPanel>
</ScrollViewer>

水平方向のみのスクロールは、 _ContentOrientation_プロパティを設定することで有効になります。 レイアウト中にコンテンツに使用される制約を決定します。 値Horizo​​ntalは、コンテンツが水平方向に制約されておらず(無限のサイズが許可されている)、ビューポートに一致するように垂直方向に制約されていることを意味します。 同様に、Vertical(デフォルト)は、垂直方向に制約がなく、水平方向に制約があることを意味します。

大きな画像をスクロールする

_Both_のContentOrientationは、コンテンツが水平方向と垂直方向の両方で制約されていないことを意味します。

<ScrollViewer Width="500" Height="400" ContentOrientation="Both">
    <Image Source="Assets/LargeEiffelTower.png"/>
</ScrollViewer>

ScrollBarの可視性の変更

この例では、常に両方のスクロールバーが非表示になっています。 ユーザーは引き続きコンテンツをどちらの方向にもパンできます。

<ScrollViewer Width="500" Height="400"
              ContentOrientation="Both"
              HorizontalScrollBarVisibility="Hidden"
              VerticalScrollBarVisibility="Hidden">
    <Image Source="Assets/LargeEiffelTower.png"/>
</ScrollViewer>

特定の種類の入力に対する組み込みサポートをオフにする

この例では、開発者は、マウスホイール入力でカスタム処理を実行し、ペンを介した投げ縄選択エクスペリエンスをサポートするキャンバスベースのアプリを作成しています。 Touchなどの他の入力を受け入れながら、これらの入力の種類を無視するようにScrollViewerを構成できます。

<ScrollViewer IgnoredInputKind="MouseWheel,Pen"
              Width="500" Height="400"
              ContentOrientation="Both" >
    <SwapChainPanel x:Name="swapChainPanel" Width="40000" Height="40000">
        ...
    </SwapChainPanel>
</ScrollViewer>

プログラマティックスクロールのアニメーションをカスタマイズする

開発者は、スライダーのValueChangedイベントをリッスンし、デフォルトのアニメーションでカスタム期間を使用してScrollViewerのVerticalOffsetをアニメーション化します。

private void VerticalOffsetSlider_ValueChanged(
    object sender,
    RangeBaseValueChangedEventArgs e)
{
    double verticalOffsetDelta = GetOffsetDelta();
    TimeSpan animationDuration = GetCustomAnimationDuration();

    // Initiate the scroll and enqueue the ScrollInfo we'll use to identify related events
    ScrollInfo scrollInfo = _scrollViewer.ScrollBy(0.0, verticalOffsetDelta);
    _myScrollRequests.Add(new MyScrollRequest(scrollInfo, animationDuration));
}

// Listen to the ScrollViewer's ScrollAnimationStarting event and customize 
// the default animation
private void ScrollViewer_ScrollAnimationStarting(
    ScrollViewer scrollViewer,
    ScrollAnimationStartingEventArgs e)
{
    MyScrollRequest myScrollRequest = _myScrollRequests.FindRequest(e.ScrollInfo);
    e.Animation.Duration = myScrollRequest.AnimationDuration;
}

// Dequeue the ScrollInfo once the action completes
private void ScrollViewer_ScrollCompleted(
    ScrollViewer scrollViewer,
    ScrollCompletedEventArgs e)
{
    _myScrollRequests.RemoveRequest(e.ScrollInfo);
}

詳細な機能設計

重要な設計の詳細を含めてください。 これには、次の1つ以上が含まれる可能性があります。-API提案(サポートされている言語または擬似コードは問題ありません)-新しいユーザーエクスペリエンスのモックアップの設計-新しいUIのアクセシビリティコンプライアンスの詳細-その他の実装上の注意

高ポリシーおよび低ポリシーのスクロール

スクローラー(低ポリシー)

Scrollerは、クロムを使用しない低レベルのビルディングブロックであり、基本的なパンおよびズームロジックをすべて提供します。 プラットフォームのさらに低いポリシーのInteractionTrackerをXAMLマークアップ対応要素としてラップします。
非常に文字通り、ScrollerはScrollViewerの「ビューポート」であり、ScrollContentPresenterの代わりになります。 ただし、Scrollerは、ScrollContentPresenterとは異なり、単にコンテンツをクリッピングするだけではありません。

Scrollerは、InteractionTrackerを直接使用できる柔軟性と、次の利点を提供します。

  • アクセシビリティサポート
  • マークアップに適した構文と使いやすいAPI
  • XAMLのレイアウトシステムおよび仮想化機能との統合

ScrollViewer(高ポリシー)

新しいScrollViewerは、Scrollerをラップし、そのプロパティを共通の値に設定します。 たとえば、 <ScrollViewer/> 、水平スクロールと垂直スクロールの両方の操作をサポートするようにScrollerを構成しますが、デフォルトのユーザーエクスペリエンスが垂直のみのスクロールであるように見えるようにコンテンツの幅を制限します(一般的なケース)。

ScrollViewerには、Scrollerを使用するよりも次の利点があります。

  • デフォルトのUX(例:スクロールインジケーター、マウス用の意識的なスクロールバー、デフォルトのアニメーションカーブ)
  • Scroller / InteractionTracker(つまり、キーボードとゲームパッド)で処理されないUIスレッドバインド入力のデフォルトサポート
  • ゲームパッドのデフォルトのフォーカス移動(ページアップ/ダウン、トリガーに応じて自動的にフォーカスを設定)
  • ユーザーのシステム設定のデフォルト認識(たとえば、Windowsでスクロールバーを自動的に非表示にする)
  • (将来)スナップポイントの簡単な構成オプション
  • (将来)より多くのマウスパンモードのサポート(例:開く/閉じる手でコンテンツをクリックアンドドラッグ、マウスホイールを介したマウスパン/「コンパス」カーソルを表示する中央ボタンクリック)

どちらを使用しますか?

アプリと多くのコントロール作成者のデフォルトの選択は、ScrollViewerを使用することです。 使いやすさが向上し、プラットフォームと一貫性のあるデフォルトのUXが提供されます。 Scrollerは、デフォルトのUX /ポリシーが必要ない場合に適しています。たとえば、改良されたFlipViewコントロールや、クロムのないスクロール面を作成します。

ScrollViewerのみのAPI

Horizo​​ntalScrollBarVisibility / VerticalScrollBarVisibility

水平スクロールバーと垂直スクロールバーの両方のデフォルト値は_Auto_です。 コンテンツがビューポートよりも広い/高いかどうかに基づいて、自動的に表示または非表示になります。

'Disabled'オプションは、新しいScrollViewerで使用可能な列挙型オプションには存在しません。 代わりに、水平方向または垂直方向にパンするユーザーインタラクションに応答するようにコントロールを構成することは、_Horizo​​ntalScrollMode_および_VerticalScrollMode_プロパティのみに基づいて行われます。

namespace Microsoft.UI.Xaml.Controls
{
    public enum ScrollBarVisibility
    {
        Auto = 0,    // Only visible when the ZoomFactor * content size > viewport
        Visible = 1, // Always visible
        Hidden = 2   // Always hidden
    }
}

下の図では、マウスカーソルが垂直スクロールバーの上にあります。 コンテンツがビューポートと同じ幅であるため、表示されるのはこれだけです。

コンテンツが両方の次元でビューポートよりも大きい場合、両方の意識的なスクロールバーと、右下隅にあるそれらのセパレータが表示されます。

スクローラーのみのAPI

Horizo​​ntalScrollController / VerticalScrollController

Scrollerは、その_Horizo​​ntalScrollController_および_VerticalScrollController_を_IScrollController_インターフェイスを実装するタイプに設定することにより、スクロールを制御するインタラクティブな「ウィジェット」に接続できます。 ScrollBarsは、そのようなウィジェットのよく知られた例です。 ScrollViewerは、そのScrollerに2つのそのようなウィジェットを提供します。 たとえば、開発者は、UIスレッドに依存しない入力のためにComposition.Visualに依存するカスタムIScrollController実装を作成できます。

_scroller.HorizontalScrollController = new Acme.Slider(orientation: Orientation.Horizontal);
_scroller.VerticalScrollController = new Acme.Slider(orientation: Orientation.Vertical);

ScrollViewer / Scrollerのダウンレベルの制限

フレームワークには、Windows 10 April 2018 Updateの時点で、カスタムスクロールコントロールを構築するために必要なすべてのフックが公開されている必要があります。 以前のリリースを対象とする場合、制限がある可能性があります。
| リリース| 制限| 理由|
|:-:|:-|:-:|
| Windows 10 Fall Creators Update(ビルド16299)以前| フォーカスを受け取ったときに要素が自動的に表示されることはありません。 | UIElementのBringIntoViewRequestedイベントは利用できません|
| | コントロールはEffectiveViewportChangedイベントに参加できません。 システムでレンダリングされたフォーカス四角形は、ビューポートの境界にクリップされません。 | UIElementのRegisterAsScrollPortは利用できません|

提案されたAPI

ScrollViewer

`` `C#
パブリッククラスMicrosoft.UI.Xaml.Controls.ScrollViewer:コントロール
{{
ScrollViewer();

// Default Value: non-null instance
Windows.UI.Composition.CompositionPropertySet ExpressionAnimationSources { get; }

/ *

  • レイアウト中心のプロパティ
    * /
    //デフォルト値:null
    UIElement Content {get; 設定; };
// Default Value: Vertical
Microsoft.UI.Xaml.Controls.ContentOrientation ContentOrientation { get; set; };

// Default Value: 0.0
Double HorizontalOffset { get; };

// Default Value: 0.0
Double VerticalOffset { get; };

// Default Value: 1.0
Single ZoomFactor { get; };

// Default Value: 0.0
Double ExtentWidth { get; };

// Default Value: 0.0
Double ExtentHeight { get; };

// Default Value: 0.0
Double ViewportWidth { get; };

// Default Value: 0.0
Double ViewportHeight { get; };

// Default Value: 0.0
Double ScrollableWidth { get; };

// Default Value: 0.0
Double ScrollableHeight { get; };

// Default Value: Auto
M.UI.Xaml.Controls.ScrollBarVisibility HorizontalScrollBarVisibility {get;set;};

// Default Value: Auto
M.UI.Xaml.Controls.ScrollBarVisibility VerticalScrollBarVisibility {get;set;};

// Default Value: Collapsed
// Used for template binding the Visibility property of the horizontal
// ScrollBar in the control template
Visibility ComputedHorizontalScrollBarVisibility{ get; };

// Default Value: Collapsed
// Used for template binding the Visibility property of the vertical
// ScrollBar in the control template
Visibility ComputedVerticalScrollBarVisibility{ get; };

/ *

  • ユーザーインタラクション中心のプロパティ
    * /
    //デフォルト値:有効
    Microsoft.UI.Xaml.Controls.ScrollMode Horizo​​ntalScrollMode {get; 設定; };
// Default Value: Enabled
Microsoft.UI.Xaml.Controls.ScrollMode VerticalScrollMode { get; set; };

// Default Value: Disabled
Microsoft.UI.Xaml.Controls.ZoomMode ZoomMode { get; set; };

// Default Value: All
Microsoft.UI.Xaml.Controls.InputKind IgnoredInputKind { get; set; };

// Default Value: Idle
Microsoft.UI.Xaml.Controls.InteractionState State { get; };

// Default Value: Auto
Microsoft.UI.Xaml.Controls.ChainingMode HorizontalScrollChainingMode { get; set; };

// Default Value: Auto
Microsoft.UI.Xaml.Controls.ChainingMode VerticalScrollChainingMode { get; set; };

// Default Value: True
boolean IsHorizontalRailEnabled { get; set; };

// Default Value: True
boolean IsVerticalRailEnabled { get; set; };

// Default Value: Auto
Microsoft.UI.Xaml.Controls.ChainingMode ZoomChainingMode { get; set; };

// Default Value: None
M.UI.Xaml.Controls.SnapPointsType HorizontalSnapPointsType { get; set; };

// Default Value: None
M.UI.Xaml.Controls.SnapPointsType VerticalSnapPointsType { get; set; };

// Default Value: Near
M.UI.Xaml.C.Primitives.SnapPointsAlignment HorizontalSnapPointsAlignment { g;s; };

// Default Value: Near
M.UI.Xaml.C.Primitives.SnapPointsAlignment VerticalSnapPointsAlignment { g;s; };

// Default Value: 0.95, 0.95
Windows.Foundation.Numerics.Vector2 ScrollInertiaDecayRate { get; set; }; 

// Default Value: 0.95
Single ZoomInertiaDecayRate { get; set; }; 

// Default Value: 0.1
Double MinZoomFactor { get; set; };

// Default Value: 10.0
Double MaxZoomFactor { get; set; };

// Default Value: 0.0
Double HorizontalAnchorRatio { get; set; };

// Default Value: 0.0
Double VerticalAnchorRatio { get; set; };

// Forwarded to inner Scroller’s IScrollAnchorProvider implementation
// Default Value: null
Windows.UI.Xaml.UIElement CurrentAnchor { get; };

/ *

  • メソッド
    * /
    //指定されたオフセットまで非同期にスクロールします。 アニメーションを許可し、
    //スナップポイントを尊重します。 ScrollInfo構造体を返します。
    Microsoft.UI.Xaml.Controls.ScrollInfo ScrollTo(
    ダブルhorizo​​ntalOffset、
    ダブルverticalOffset);
// Asynchronously scrolls to specified offsets with optional animation,
// with optional snap points respecting. Returns a ScrollInfo struct.
Microsoft.UI.Xaml.Controls.ScrollInfo ScrollTo(
    double horizontalOffset,
    double verticalOffset,
    Microsoft.UI.Xaml.Controls.ScrollOptions options);

// Asynchronously scrolls by the provided delta amount.
// Allows animation, respects snap points. Returns a ScrollInfo struct.
Microsoft.UI.Xaml.Controls.ScrollInfo ScrollBy(
    double horizontalOffsetDelta,
    double verticalOffsetDelta);

// Asynchronously scrolls by the provided delta amount with
// optional animation, with optional snap points respecting.
// Returns a ScrollInfo struct.
Microsoft.UI.Xaml.Controls.ScrollInfo ScrollBy(
    double horizontalOffsetDelta,
    double verticalOffsetDelta,
    Microsoft.UI.Xaml.Controls.ScrollOptions options);

// Asynchronously adds scrolling inertia. Returns a ScrollInfo struct.
Microsoft.UI.Xaml.Controls.ScrollInfo ScrollFrom(
    Vector2 offsetsVelocity,
    Nullable<Vector2> inertiaDecayRate);

// Asynchronously zooms to specified zoom factor. Allows animation
// (respects snap points in v2). Returns a ZoomInfo struct.
Microsoft.UI.Xaml.Controls.ZoomInfo ZoomTo(
    float zoomFactor,
    Nullable<Vector2> centerPoint);

// Asynchronously zooms to specified offsets with optional animation
// (with optional snap points respecting in v2). Returns a ZoomInfo struct.
Microsoft.UI.Xaml.Controls.ZoomInfo ZoomTo(
    float zoomFactor,
    Nullable<Vector2> centerPoint,
    Microsoft.UI.Xaml.Controls.ZoomOptions options);

// Asynchronously zooms by the provided delta amount. Allows animation
// (respects snap points in v2). Returns a ZoomInfo struct.
Microsoft.UI.Xaml.Controls.ZoomInfo ZoomBy(
    float zoomFactorDelta,
    Nullable<Vector2> centerPoint);

// Asynchronously zooms by the provided delta amount with optional animation
// (with optional snap points respecting in v2). Returns an ZoomInfo struct.
Microsoft.UI.Xaml.Controls.ZoomInfo ZoomBy(
    float zoomFactorDelta,
    Nullable<Vector2> centerPoint,
    Microsoft.UI.Xaml.Controls.ZoomOptions options);

// Asynchronously adds zooming inertia. Returns a ZoomInfo struct.
Microsoft.UI.Xaml.Controls.ZoomInfo ZoomFrom(
    float zoomFactorVelocity,
    Nullable<Vector2> centerPoint,
    Nullable<float> inertiaDecayRate);

/ *

  • 内部ScrollerのIScrollAnchorProvider実装に転送されます
    * /
    void RegisterAnchorCandidate(UIElement element);
    void UnregisterAnchorCandidate(UIElement element);

/ *

  • イベント
    * /
    // Horizo​​ntalOffset、VerticalOffset、ZoomFactorのいずれかが発生するたびに発生します
    //依存関係プロパティが変更されました。
    イベントTypedEventHandlerViewChanged;
// Raised when any of the ExtentWidth and ExtentHeight dependency property changed.
event TypedEventHandler<ScrollViewer, Object> ExtentChanged;

// Raised when the State dependency property changed.
event TypedEventHandler<ScrollViewer, Object> StateChanged;

// Raised when a ScrollTo or ScrollBy call triggers an animation.
// Allows customization of that animation.
event TypedEventHandler<ScrollViewer, Microsoft.UI.Xaml.Controls.ScrollAnimationStartingEventArgs>
    ScrollAnimationStarting;

// Raised when a ZoomTo or ZoomBy call triggers an animation.
// Allows customization of that animation.
event TypedEventHandler
    <ScrollViewer, Microsoft.UI.Xaml.Controls.ZoomAnimationStartingEventArgs>
    ZoomAnimationStarting;

// Raised at the end of a ScrollTo, ScrollBy, or ScrollFrom asynchronous
// operation. Provides the original ScrollInfo struct.
event TypedEventHandler
    <ScrollViewer, Microsoft.UI.Xaml.Controls.ScrollCompletedEventArgs>
    ScrollCompleted;

// Raised at the end of a ZoomTo, ZoomBy, or ZoomFrom asynchronous operation.
// Provides the original ZoomInfo struct.
event TypedEventHandler
    <ScrollViewer, Microsoft.UI.Xaml.Controls.ZoomCompletedEventArgs>
    ZoomCompleted;

// Raised at the beginning of a bring-into-view-request participation.
// Allows customization of that participation. 
event TypedEventHandler
    <ScrollViewer, Microsoft.UI.Xaml.Controls.BringingIntoViewEventArgs>
    BringingIntoView;

// Raised to allow the listener to pick an anchor element, when anchoring
// is turned on.
event TypedEventHandler
    <ScrollViewer, Microsoft.UI.Xaml.Controls.AnchorRequestedEventArgs>
    AnchorRequested;

/ *

  • 依存関係のプロパティ
    * /
    static DependencyProperty ContentProperty {get; };
    static DependencyProperty ContentOrientationProperty {get; };
    static DependencyProperty ComputedHorizo​​ntalScrollBarVisibilityProperty {get; };
    static DependencyProperty ComputedVerticalScrollBarVisibilityProperty {get; };
    static DependencyProperty Horizo​​ntalScrollBarVisibilityProperty {get; };
    static DependencyProperty VerticalScrollBarVisibilityProperty {get; };
static DependencyProperty IgnoredInputKindProperty { get; };
static DependencyProperty HorizontalScrollModeProperty { get; };
static DependencyProperty VerticalScrollModeProperty { get; };
static DependencyProperty ZoomModeProperty { get; };
static DependencyProperty HorizontalScrollChainingModeProperty {g};
static DependencyProperty VerticalScrollChainingModeProperty {g};
static DependencyProperty IsHorizontalRailEnabledProperty {g};
static DependencyProperty IsVerticalRailEnabledProperty {g};
static DependencyProperty ZoomChainingModeProperty { get; };
static DependencyProperty MinZoomFactorProperty { get; };
static DependencyProperty MaxZoomFactorProperty { get; };
static DependencyProperty HorizontalAnchorRatioProperty { get; };
static DependencyProperty VerticalAnchorRatioProperty { get; };

}
`` `

未解決の質問

  • レイアウト制約をコンテンツに適用する方法に影響を与えるContentOrientationプロパティ(または別の名前のプロパティ)を使用すると、作業がより複雑または簡単になりますか?
  • ScrollViewerが厳密にスクロールに関するものになるように、ズーム関連のAPIを派生コントロール(ZoomViewerなど)に分離する必要がありますか?
Epic area-Scrolling feature proposal proposal-NewControl team-Controls

最も参考になるコメント

それは正しい。 私たちは3つの状況を念頭に置いていました:

  1. 私は自分の現在の位置が何であるかを気にしません。 特定の目的地までスクロール/ズームしたい。
  2. 私は自分の現在の位置が何であるかを気にし、その位置に対して特定の量だけスクロール/ズームしたいと思います。
  3. 最終目的地が何であるかは気にしません。 現在の位置からスクロール/ズームしたいだけです。

後者のシナリオは、マウスホイールをクリックしてパンを体験するようなものかもしれません。 クリックしたときのカーソルの位置に応じて、現在の位置からスクロールして慣性が挿入されます(それが何であれ)。

全てのコメント61件

私の考えでは、スクロールできるコンテンツとズームできるコンテンツの必要性は大きく異なります。 コンテンツをズームすると、スクロールする必要があることもよくありますが、これらの個別のコントロールを作成することを検討したかどうか知りたいのですが。 おそらく、スクロールコントロールから拡張可能なズーム可能なコントロールを使用します。
私の懸念は次のとおりです。1)ほとんどの人が必要としないズーム関連の機能を追加することにより、ScrollViewerが過度に複雑になっている。 2)ScrollViewerがこれをサポートしていることは、コンテンツにズームインするためのコントロールを探している人には明らかではありません。


さらに、提案内で、スクロールビューア内の特定の要素にスクロールする機能が必要です。 理論的には、これは開発者がその前にすべてのアイテムを測定し、適切なオフセットまでスクロールすることで実行できますが、仮想化リストではこれを行うのが難しい場合があり、(私の考えでは)多くのアプリ(および開発者)は、これが組み込まれていることでメリットが得られます。
アイテムが「リスト」のどこに追加され、開発者がアイテムが表示されるようにしたい場合を検討してください。 または、マスター/詳細ビューを備えたページを検討してください。ページはリストのずっと下の詳細アイテムで開かれますが、開発者はマスターリストで選択されたアイテムが表示されるようにしたいので、詳細ビュー。

同様に、スクロール可能な領域内の他のアイテムがビジュアルツリーから削除(または追加)されている間、アイテムが表示領域にとどまるようにすることも役立ちます。 これを行う最善の方法はわかりませんが、背景(またはUI以外のスレッド)アクションによってスクロール可能領域に他のアイテムが削除または追加されるため、スクロール可能領域内の選択されたアイテムが移動するのは非常に悪いことです。
クリック/タップするときにアイテムを動かすと、ひどいユーザビリティ体験につながります。 フォーカスされた/選択されたアイテムが表示領域の外に移動すると、アクセシビリティツールやスクリーンリーダーで問題が発生する可能性もあります。
アイテムが移動している間(特にそのアイテムが他の場所から削除された場合)、アイテムを同じ位置に維持しようとすると潜在的な問題があることは承知していますが、何もしないと十分ではないようです。

@mrlaceyに感謝します。 この提案だけでなく、既存のScrollViewerでもズーム機能が見つけにくいことがわかります。 これは、既存のUWP ScrollViewerからの別の出発点になるため(おそらくより良いのでしょうか?)、議論のための未解決の質問として追加しました。

最初に特定の要素を作成してレイアウトシステムを実行し、スクロールできる位置にする必要がある場合があるため、仮想化は物事を複雑にします。 これが、過去に特定のコントロール(つまり、ListView)に、上記を簡単に処理する独自のScrollIntoViewメソッドがあったStartBringIntoViewメソッドがあり、これを使用してアイテムに非常に簡単にスクロールできます。また、ビューポートのどこに表示されるかをきめ細かく制御するためのオプション

Re:他のコンテンツが追加/削除されたり、サイズが変更されたりしても、アイテムの位置を維持します...何もしないだけでは不十分であることに完全に同意します。 これがまさにスクロールアンカー機能が存在する理由です。 :)これまで、ListView / GridViewの仮想化パネルに組み込まれていたのはあまり知られていない機能です。 最近のリリースでは、このようなものをListViewでのみ使用できるようにすることを明確に試みています。

拡張されたScrollViewerのアイデアを検討する場合は、おそらくFluent Designチームが、デフォルトでz-depth値が設定された視差とアイテムの処理についてアドバイスすることができます。

XAMLがMRアプリの3D表現に移行し、深度とシャドウが2D XAMLに移行すると、スクロールによってさまざまな深度値のアイテムがどのように移動するか、シャドウがスクロールインジケーターの上または後ろにどのようにレンダリングされるか、その他の問題が発生する可能性がありますXAMLチームの3D実験では、Windows UIライブラリがゆっくりと新しいデフォルトになるため、新しいデフォルトになる可能性のあるものに組み込むことができます。

私の考えでは、スクロールできるコンテンツとズームできるコンテンツの必要性は大きく異なります。

Webブラウザー、グラフィックデザインアプリ、オフィスアプリ、PDFビューアーを除き、コンテンツドキュメントを表示するものはすべて。

@mrlaceyに同意して、特定の要素をビューに表示することと、ビューのどこに表示するか(上、中央、下など)を指定することが重要であることに同意します。 要素が完全に表示されているか、クリップされているかを検出する方法も必要です。 このようにして、要素がすでに完全にまたは部分的に表示されていることがわかっている場合は、ビューをスクロールして要素を表示する必要はありません。

皆さんありがとう! アプリがマークアップに設定する傾向のあるプロパティに関するテレメトリを収集しました。ZoomModeは* ScrollModeと* ScrollBarVisibilityの直後に表示されます。 ほとんどの場合、アプリはプロパティを変更していません。 ScrollModeプロパティとScrollBarVisibilityプロパティが設定されているときに私が観察したのは、コンテンツの水平スクロールを有効にすることが多いということです。 ContentOrientationプロパティの導入は、それを簡単にすることを目的としています。 水平スクロールの後、次に最も一般的なシナリオはズームです。

ズームの発見可能性に対処するために別個の(派生した)コントロールを導入するのではなく、適切なドキュメント/サンプルがより効果的である可能性があると私は信じています。

ビヘイビアまたはコンテキスト列挙型を追加するのはどうですか?

ScrollViewer.ScrollBehaviour = ScrollBehaviour.Zoom;
ScrollViewer.ScrollBehaviour = ScrollBehaviour.Scroll;
ScrollViewer.ScrollBehaviour = ScrollBehaviour.ParallaxScroll;

ScrollViewer.ScrollBehaviour = ScrollBehaviour.Zoom;は非常に混乱します。 ZoomModeはそのままにしておくべきだと思います。

ScrollViewer.ScrollBehaviour = ScrollBehaviour.Zoom;は非常に混乱します。 ZoomModeはそのままにしておくべきだと思います。

私はおそらく、スクロールではなく、コンテンツのズームのための派生コントロールがあるべきだと考えるコメントに対処するものとして提案の前に置くべきでした

私にとって、特にタッチデバイスでは、ズーム機能をScrollViewerに組み込むことは実際には理にかなっています。 現在、UWPの画像/コントロールでフリースタイルのパン/ズーム/回転を行う簡単な方法はありません。StackOverflowとGitHubで多くの関連する質問があります(ドラッグ可能なコンテンツコントロールの追加など)。

@micahl 、私はズームと仮定します

回転ジェスチャをサポートする

このシナリオは将来ネイティブにサポートされますか?

私にとって、特にタッチデバイスでは、ズーム機能をScrollViewerに組み込むことは実際には理にかなっています。 現在、UWPの画像/コントロールでフリースタイルのパン/ズーム/回転を行う簡単な方法はありません。StackOverflowとGitHubで多くの関連する質問があります(ドラッグ可能なコンテンツコントロールの追加など)。

ズームとスクロールをさらに制御する必要がある場合...

ScrollViewer.ScrollBehaviour = ScrollBehaviour.ZoomAndScroll;

しかし、タッチデバイスでは、指をつまんだりスライドさせたりできるのは自然なことです。 ただし、タッチせずにズームするには、[+]ボタンと[-]ボタンが表示される必要があります。 または、ズームのみの場合は、スクロールバーの親指をドラッグするとズームインおよびズームアウトします。

Microsoft Word UIを見ると、ステータスバーにズームコントロールがあります。 また、ドキュメント領域のスクロールバー。

マウスズームは、新しいScrollViewerコントロールに組み込む必要があるものをサポートしていますか? では、ZoomModeがオンの場合、またはBehaviorプロパティでZoomが許可されている場合、プラスボタンとマイナスボタンが表示されますか?

@JustinXinLiu回転ジェスチャをサポートするには、InteractionTracker(@likuba)からのサポートが必要になる可能性があります。

@mdtauk新しいScrollViewerは、既存のScrollViewerと同様に、Ctrl +マウスホイールを介したマウスホイールズームをサポートします。 ズームが有効になっているときに、コントロールにデフォルトのプラス/マイナスボタンが必要かどうかはわかりません。 私の現在の印象では、ズームを一般的に有効にする種類のアプリ(コンテンツドキュメントアプリなど)は、さまざまな方法でそれらのボタンをアプリエクスペリエンスに組み込むことを選択します。 たとえば、スライダーで区切られたステータスバー(Officeなど)の-/ +や、他のコマンド(マップなど)の下に垂直に表示される単純な-/ +などです。

@micahlScrollFromがそのように呼ばれる理由がわかりません。 ScrollByと同じではありませんが、ベロシティパラメーターがありますか?

@adrientetarは、ScrollFromという名前を付ける代わりに、異なるパラメーターのセットを使用してScrollByをオーバーロードしない理由を尋ねていますか?

ええ、私は推測します😃しかし、ScrollFromの背後にある概念は、与えられた速度で方向に移動することだと思いますか? 特定のポイントに移動するだけのScrollByとは対照的です。

それは正しい。 私たちは3つの状況を念頭に置いていました:

  1. 私は自分の現在の位置が何であるかを気にしません。 特定の目的地までスクロール/ズームしたい。
  2. 私は自分の現在の位置が何であるかを気にし、その位置に対して特定の量だけスクロール/ズームしたいと思います。
  3. 最終目的地が何であるかは気にしません。 現在の位置からスクロール/ズームしたいだけです。

後者のシナリオは、マウスホイールをクリックしてパンを体験するようなものかもしれません。 クリックしたときのカーソルの位置に応じて、現在の位置からスクロールして慣性が挿入されます(それが何であれ)。

おかげで、それは物事をクリアします。 私は自分のマウスホイールクリック体験のためにScrollByを使用することをもっと探していると思いますが、特定の場合にScrollFromが役立つことがわかります。

現在のScrollViewerコントロールでは、ViewportWidthプロパティとViewportHeightプロパティにバインドできますが、これは現在、新しいScrollViewerコントロールではできないようです。 これは追加されますか?

@lhak 、これらの値を何にバインドしますか? それらを追加することは大きな変化ではありません。 シナリオのコンテキストに応じて、拘束するのではなく、異なるアプローチをお勧めします。 ある場所から別の場所への移動を困難にする違いに敏感になりたい一方で、より良い代替案を宣伝したいと考えています。

@micahl過去にもいくつかの計算にこれらの値を使用したことがあると確信しています。 私が彼らに縛られているかどうかわからない。

@ michael-hawker明確にするために、プロパティはScrollViewerで利用可能になります。 ただし、提案されたAPIでは、それらはDependencyPropertiesではなく通常のプロパティとして公開されています。 これらの同じ値は、誰かがコンポジションに基づいて入力駆動型アニメーションを作成している状況で、ExpressionAnimationSourcesプロパティの一部として使用できます。

私は現在、アプリケーションで次のようなコードを使用しています。

<ScrollViewer x:Name="outputScrollViewer">
  <Viewbox MaxWidth="{x:Bind outputScrollViewer.ViewportWidth, Mode=OneWay}" MaxHeight="{x:Bind outputScrollViewer.ViewportHeight, Mode=OneWay}">
    <TheXamlElement Width=X Height=Y/>
  </Viewbox>
</ScrollViewer>

これにより、アスペクト比を維持しながら、内側のxaml要素(固定サイズ)をスクロール/ズームすることができます。 動作は、xaml要素がscrollviewerのビューポートよりも小さくなることはないことを除いて、画像を表示する写真アプリと同様です。

@lhak 、良いシナリオ! このシナリオが現在の提案にどのように対応できるかを大声で考えてください... ContentOrientationプロパティに別のオプションを追加できると思います。 提案の現在のオプション:

  • なし=優先方向はありません。 コンテンツに両方向で利用可能なサイズを無限に与えます。
  • 水平=コンテンツに使用可能なサイズを水平方向にのみ無限に指定し、レイアウト中に高さをビューポートに制限します。
  • 垂直=水平の転置

4番目のオプションは、レイアウト中の高さと幅の両方をビューポートのサイズに制限することです。 今のところ、これを「ビューポート」オリエンテーションと呼びますが、そのように名前を付けることについてはさまざまな反応があります。
少なくとも(より一般的な?)画像の場合は、レイアウトプロセスの一部として「正しいこと」が発生するため、ビューボックスとバインディングが不要になると思います。

<ScrollViewer ContentOrientation="Viewport">
  <Image Stretch="Uniform" .../>
</ScrollViewer>

より複雑なコンテンツの場合は、ビューボックスでラップしても、バインディングをスキップできます。

<ScrollViewer ContentOrientation="Viewport">
  <Viewbox>
    <TheXamlElement Width=X Height=Y/>
  </Viewbox>
</ScrollViewer>

@micahl別の質問があります

マウスホイールを手動で処理する必要があるかもしれませんが、コントロールの機能を再実装する必要があることが判明した場合は残念です。 私たちはあなたが求めているものを達成する方法があるかもしれないと思います。 その要点は、ZoomInertiaDecayRateを1.0に近い値に設定してから、繰り返しズームスナップポイントを定義することです。 ZoomInertiaDecayRateプロパティを追加し、必須のスナップポイントに関連するいくつかの問題を修正したら、これを試してみてください。

それが機能しない場合は、IgnoredInputKind = "Mousewheel"を設定し、Scrollerをサブクラス化してOnPointerWheelChangedをオーバーライドするか、ScrollerのPointerWheelChangedイベントのイベントハンドラーを追加することで、自分で処理しようとすることにフォールバックできます。

@micahlありがとう! マウスホイールの動作をどのシナリオに対して調整したかはわかりません。個人的には、Adobe XDなどの方法が好きです。アニメーションが少し加速しているように見えますが、きびきびとしていて、ズームの増分が十分に大きくなっています。 スクローラーのマウスホイールのズームアニメーションは少し遅く感じ、ズームの増分が非常に小さくなっています。

@adrientetar 、良いフィードバック。 調整を検討することができます。

増分と値を制御するあらゆる種類の変数-オーバーライド可能なプロパティにすることができます

右。 ここでの1つの課題は、Win10バージョン1809以降では、コントロールがマウスホイール入力を基になるInteractionTrackerに渡して、UIスレッドから処理してスムーズな動きを可能にすることです。 これらのオーバーライド可能なプロパティは、最初に下位レベルで公開する必要があります。 1809より前のバージョンのWin10では、UIスレッドでマウスホイール入力を制御処理するロジックを追加しています。

オーバーライド可能なプロパティを公開する動作を検討できます。明示的に設定されている場合は、UIスレッドでコントロールプロセスのマウスホイールを使用することにフォールバックします。 これらのプロパティが下位レベルに存在する場合は、それらに依存してコンポジターにキックバックするように切り替えることができます。 スクロールはおそらくマウスホイールほどスムーズではないでしょう。 おそらくそれはここで大丈夫ですか?

では、現在のズーム動作は、オーバーライドする方法なしで、InteractionTrackerに組み込まれていますか? そして、下位互換性が失われるため、変更する方法はないと思います🤔cc@ likuba

ここで役立つInteractionTrackerのオプションがいくつかあると思います😊。 具体的には、 PointerWheelConfigDeltaScaleModifierなどの機能を構築して、これらのタイプのカスタマイズを可能にしました。 同期して、コントロール内でこれらを使用することで、上記の問題/リスクなしにここで何かが発生する可能性があるかどうかを確認します。

@micahl私が取り組んでいるプロジェクトで興味深い状況があり、PoC用に独自のスクロールビューアーを作成する必要がありました-しかし、何か計画があるかどうか(またはこのコントロールがすでにこれをサポートしているかどうか)を知りたいです次のシナリオ:
10000x5000の巨大なキャンバスがあるとすると、その周りを移動するには、スクロールビューアにカプセル化します。
これで、キャンバスに2つ(またはそれ以上)のInkCanvasesがあり、異なる指または1本の指と1つのマウスポインターを使用して、両方(またはそれ以上)に書き込みたいと考えています。 このコントロールでどのようにそれを達成しますか(またはそれは可能ですか)? :)
私が見たデフォルトの動作は、1つのInkCanvasを描画しているときに他の何かに触れるとすぐに、その特定のInkCanvasが「PointerLost」を起動します。それだけです。他に何もする必要はありません。
明らかに、私のスクロールビューアーは、私が自分で書いたように完璧にはほど遠いので、このコントロールでこれが可能かどうかを調べていますか?

よろしくお願いします!

こんにちは@stefangavrilasengage 、興味深いシナリオ。 :) PoCから、指がInkCanvasに降りてから動き始めたときに予想される動作は何ですか? 描画しますか、それともパンしますか?

こんにちは@ micahl-返信ありがとうございます! これまでに、デジタルホワイトボードアプリのようなものだと推測していると思います。
今、私は現在何が起こっているかを提示します:

  • ScrollViewer(デフォルト):InkCanvasに1本の指で描画しても問題ありません。 人差し指で1番目のInkCanvasの入力が失われます。
  • ScrollViewerEx(カスタムコントロール):描画するためにできるだけ多くの指とInkCanvasesを使用し、それは機能します。

これは役に立ちますか? :)
ありがとうございました !

@stefangavrilasengageシングルタッチジェスチャがパンするか(ScrollViewerのデフォルトの動作)、インクを描画するかを明確にするものを尋ねていました。 そこには固有の対立があります。 どのように解決しますか? 地図のようにスクロールするには2本の指が必要ですか? 編集ボタンを使用して編集モードを開始/終了しますか? NS...

@micahlお詫びします-私がどのように対立を解決したかについて言及するのを忘れました。
キャンバス上にあるオブジェクトのインクは、Win2Dコンテナ内にあります。 各オブジェクトの編集モードに入った場合にのみ、InkCanvasが編集用に上部に表示されます(カスタム乾燥を使用)。
したがって、私の状況では(これが他の誰かに当てはまるかどうかはわかりません)、InkCanvasがアクティブな「ドローアブル」である場合、ScrollViewerには何も表示されません。
もしあれば、これが当てはまらないと思うユースケースを知りたいと思いますか?

ありがとう !

@micahlと私がgithubの問題で

@micahlと私がgithubの問題で

申し訳ありません! 編集しました!

@micahgodboltそれが最後ではないかもしれません。 ;)
@stefangavrilasengageありがとう! それは私の質問に答えます。 複数のInkCanvasコントロールを含むCanvasの親として、ScrollViewerをBorderのようなものと交換しても、同じ問題が発生しないことに気付きました。 そのため、ScrollViewer内で発生したときに、マルチ入力/マルチInkCanvas機能が機能しなくなる原因を理解するために、社内で何人かの人々に連絡を取りました。

@stefangavrilasengage 、なぜそれが機能しないのかを理解するには、ある程度の時間/調査が必要です。 この提案とは別にそれを追跡しましょう。 あなたはそれのために問題を開きますか?

@micahl Scrollerに問題があり、OnControlLoadedでコンテンツをスクロールおよびズームすると、間違った位置に配置されます。 スクロールするだけでは正しい位置になりますが、スクロールした直後にズームすると、centerPoint = nullを指定したにもかかわらず、完全にオフの位置になり、デフォルトでビューポートの中心になります(コードを見ると、ドキュメントはまだありません)。 このコードで

試してくれてありがとう、@ adrientetar! このスレッドを提案に集中させておきましょう。 あなたが見ているもののために別の問題を開くことができますか? その議論のどこに行き着くかによっては、このスレッドに戻って、提案の変更が必要かどうかを議論したいと思うかもしれません。

@micahl ExtentChanged / StateChanged / ViewChangedイベントの引数としてオブジェクトがあり、Stateメンバーを持つStateChangedEventArgsなどがないのはなぜですか? InteractionTrackerが別のスレッドで実行されているとすると、メッセージパッシングパターン(引数付きのイベント)は、イベントハンドラーのコントロールプロパティをクエリするよりも優先されませんか?

https://github.com/XeorgeXeorge/Extended-Image-Viewer

大したことではありませんが、このリポジトリの最初の部分では、水平/垂直スクロールバーがロック(無効)されている場合でもズームを実装する方法を紹介しています。

簡単に言えば:
に強制的にフィットさせながら、ズームインしたコンテンツをパンできます
効果的な垂直/水平ビューポート。

これを投稿するとき、実際に機能的なズーム操作を取得するには、ScrollViewerでHorizo​​ntalScrollbarVisibilityプロパティを有効にする必要があります。これを回避するためのより良い方法があるかもしれませんが、一緒に廃棄したデュアルスクロールビューアーソリューションで十分かもしれないと思います足りる。

@micahlアニメーション化されていないズームを実行すると、ScrollerがStateChangedイベントを送信しないようですが、これは仕様によるものですか?
https://github.com/microsoft/microsoft-ui-xaml/issues/541#issuecomment -488749469で提案されているように、Scrollerがアイドル状態になったときにCanvasVirtualControlのスケーリングを設定して、コントロールがラスター化されすぎないようにし

@adrientetar 、フレームワークとアプリの間を行き来するイベント引数を作成するためのオーバーヘッドがあります。 イベント引数は送信者によって公開されたプロパティのコピーのみを提供するため、現在の設計ではイベント引数を持たないようにしています。

はい、現在の設計では、アニメーション化されていないズームでは、プログラムで呼び出すStateChangedは起動しません。 ZoomCompletedおよびScrollCompletedイベントは、プログラムの変更に応じて発生します。 IIRCは、ユーザーからの変更によってトリガーされません。 おそらくStateChangedと組み合わせて、それらの1つを使用できます。 fyiのように、ViewChangedイベントは、ビューが変更されるたびに(ユーザーまたはプログラムによって)発生します。これにより、非常にパフォーマンスに敏感なコードパスになり、使用したいものではなくなります。

私たちはまだフィードバックを聞いているので、物事が鈍いと思われる場合はお知らせください。

はい、現在の設計では、アニメーション化されていないズームでは、プログラムで呼び出すStateChangedは起動しません。

ああ、わかりました。 イベントは常に発生し、SetFocusなどのオリジンパラメータを含む可能性がありますが、それを行うにはオーバーヘッドが発生する可能性があります。

ZoomCompletedおよびScrollCompletedイベントは、プログラムの変更に応じて発生します。 IIRCは、ユーザーからの変更によってトリガーされません。

さて、私のユースケースでは、変更がプログラムであるかどうかに応じて、State == Idleの場合、ZoomCompletedとStateChangedを処理する必要があります。 変じゃない? つまり、同じものに異なる名前の異なるイベントを設定することは、異なる方法でのみトリガーされます🤔

@RBridと私は、新しい状態「移行中」の導入といくつかのマイナーな名前変更について簡単なチャットをしました。 これがあなたのユースケースにとってより理にかなっているのかどうか私たちに知らせてください。

議論されたアイデアは、スクロール/ズーム位置への変更が処理されようとしているとき(ユーザーが開始したかプログラムであるかに関係なく)、StateChangedイベントを発生させ、現在の状態を遷移として報告するというものでした。 プログラマティックスクロール(アニメーション化されたものとアニメーション化されていないもの)のシーケンスは次のようになります。

//プログラムによるリクエスト、アニメーション
myScrollInfo = ScrollTo(100、animate = true);
//数ティック
StateChangedが発生しました(Scroller.State == Transitioning)
//数ティック
StateChangedが発生しました(Scroller.State == Animating)
//多くのダニ
StateChangedが発生しました(Scroller.State == Idling)

//プログラムによるリクエスト、アニメーションなし
myScrollInfo = ScrollTo(100、animate = false);
//数ティック
StateChangedが発生しました(Scroller.State == Transitioning)
//数ティック
StateChangedが発生しました(Scroller.State == Idling)

相互作用以上のものを表すため、InteractionState列挙型の名前をScrollStateのような名前に変更することをお勧めします。

enum ScrollState
{
    Idling = 0,
    Transitioning = 1,
    Interacting = 2,
    Inertial = 3,
    Animating = 4,
};

@micahlはい、それは私が期待するものと非常によく似ています! アニメーション化された変更のみを処理したい人は、アニメーション化状態を傍受できます。 名前については、アイドル状態(「スクローラーがアイドル状態」/「スクローラーがアニメーション化中」)、遷移→攪拌を維持しますか? (遷移は非常に混乱します。モーションの開始時なので、imoの攪拌がうまくいく可能性があることを伝えたいと思い

かき混ぜることで、最初はブレンドを考えました。 :) APIレビューは、名前を確定するときに考慮したいと思うでしょうし、前例を探す傾向があります。 いくつかのオプションがあることは常に良いことです。 他の選択肢は、不明または保留中の可能性があります。 アイドルと一緒にそれらの両方の既存のAPIに前例があります。これは、おそらくアイドリングを行わないことを意味します。

かっこいい。 保留中のsgtm、imo Unknownは、移行よりもさらに混乱します。

@ micahl-機能要件番号3には、次のサブポイントが含まれています。

効果的なビューポートの変更に参加する(必須)

そのサブポイントは、既存のイベントFrameworkElement.EffectiveViewportChangedます。 そのサブポイントは、コンテンツの非同期オンデマンド部分ロードも要件/優先順位であると(間接的に)言うのに十分ですか? たとえば、MS EdgeがPDFドキュメント(またはSVGやその他の複雑なドキュメント)の拡大ページを表示するときのScrollViewerの動作と同等です。 たとえば、ズームが900%の場合、次の2つの理由により、PDFページ全体が900%のサイズで事前レンダリングされません。

  • このレンダリングタスク(ズーム率が高い場合)には、ドキュメントの複雑さ(ベクトル要素の量、効果など)、ドキュメントサイズ、ズーム率に応じて、約3 ..20秒かかります。 この遅延は、エンドユーザーが受け入れるには大きすぎます。
  • PDFページ全体のレンダリングされた画像(ビットマップ)は、ズーム率が高い場合、非常に高いDPIでのレンダリングと同等であるため、数百メガバイトのRAMを消費する可能性があります。

MS Edgeは、ズームインされたPDFページの一部をオンデマンドでレンダリングします。つまり、ユーザーがそれらの部分をスクロールして表示します。 この手法により、ページが表示されるまでの長い遅延が回避されます。 機能要件がこのシナリオに明示的に言及していることをお勧めしますが、 async Task間接的なサポートもあります。 レンダリングされていない(またはすぐに利用できない)パーツがスクロールされて表示されると、ScrollViewerはそのスペースを構成可能なBrushで一時的に埋めてからイベントをトリガーし、イベントハンドラーはasync Task開始できます。パーツをレンダリング(または取得/ロード)します。 その後、 Task完了すると、レンダリング/取得/ロードされた部分がScrollViewerに表示され、一時的にBrush埋められたスペースが覆われます。

この問題は、高ズームでのレンダリングのコストが高いことだけではありません。 オンデマンドで取得されるコンテンツにも適用できます。 たとえば、ScrollViewerに表示される地図や衛星画像を想像してみてください。 マップの一部は、ユーザーがスクロールして表示したときにのみサーバーからダウンロードされます。

ScrollViewerが厳密にスクロールに関するものになるように、ズーム関連のAPIを派生コントロール(ZoomViewerなど)に分離する必要がありますか?

ScrollViewer.ZoomFactorが追加されたことに感謝していますが、ScrollViewerに直接追加されていることに驚きました。 ズームを別のクラス(必ずしも派生クラスである必要はありません)に配置する方が簡単で信頼性が高いと思いました。 少なくとも3つの方法が可能です。

  1. このクラスは、おそらくという名前ZoomViewer継承していないことScrollViewerが、使用していますScrollViewer子要素(そののようにインスタンスをControlTemplate )。
  2. ScrollViewer継承するおそらくZoomableScrollViewerという名前のクラス。
  3. 過度に複雑または乱雑でない場合ScrollViewer

17マウスの中クリックとスクロールをサポートするデフォルトのUXを提供します。 (したほうがいい)
18マウスでクリックしてパンするモードをサポートします(PDFビューア内でコンテンツを移動するなど)。 (したほうがいい)

18は17よりもはるかにうまく機能し、実際には17を使用する人はほとんどいないため、17のサポートを削除するかどうかを検討することをお勧めします。 確かに、17はあなたの意図した意味以外の何かを意味していると思うかもしれません(17の説明は1文だけであり、それが私が思っていることを意味するかどうかは100%確信していません)。 18は非常に使いやすく使いやすいと言うのは正しいのではないでしょうか。17は誰もが使いづらくて使いにくいものです。
(この問題は、アクセシビリティの理由で17が必要な場合に変更されますが、これまでのところ、17がアクセシビリティの問題であると誰もが言うのを聞いたことがありません。)

4入力駆動のアニメーションを実行できる

4番目はアクセシビリティ関連の問題です。 ScrollViewer(およびWinUIの他のすべてのコントロール)がアクセシビリティ設定を尊重するように要求したいと思います。

Windows10->スタート->設定->アクセスのしやすさ->表示-> Windowsでアニメーションを表示する(オンまたはオフ)。

残念ながら、何年にもわたって、MicrosoftアプリがWindowsのアクセシビリティ設定を無視する多くの例に気づきました。 アニメーションはオフになっていますが、Microsoftアプリはとにかくアニメーションを表示します。 これは、これらのアクセシビリティ設定に依存しているユーザーにとって実際の問題を引き起こします。 誰もが負の副作用を被ることなくアニメーションを楽しむことができるわけではありません。 アニメーションなどの表示に問題がないユーザーは、Windowsのユーザー補助設定の重要性を理解するのが難しいと感じることがあります。

こんにちは@ verelpode@ predavidが新しいScrollViewerの作業を推進するので、私は彼女に任せます。

17マウスの中クリックとスクロールをサポートするデフォルトのUXを提供します。 (したほうがいい)
18マウスでクリックしてパンするモードをサポートします(PDFビューア内でコンテンツを移動するなど)。 (したほうがいい)

18は17よりもはるかにうまく機能し、実際には17を使用する人はほとんどいないため、17のサポートを削除するかどうかを検討することをお勧めします。 確かに、17はあなたの意図した意味以外の何かを意味していると思うかもしれません(17の説明は1文だけであり、それが私が思っていることを意味するかどうかは100%確信していません)。 18は非常に使いやすく使いやすいと言うのは正しいのではないでしょうか。17は誰もが使いづらくて使いにくいものです。
(この問題は、アクセシビリティの理由で17が必要な場合に変更されますが、これまでのところ、17がアクセシビリティの問題であると誰もが言うのを聞いたことがありません。)

@verelpode 17を正しく理解していると思いますが、18の方が重要で、通常は17よりも直感的であることに同意します。ただし、「左クリックアンドドラッグ」が選択やドラッグアンドドロップなどの他の目的ですでに使用されているシナリオもあります。 。 このようなシナリオでは、アプリがミドルクリックによるスクロールを有効にできると便利です(17)。

私は個人的にブラウザでミドルクリックスクロールを時々使用します。左クリック+ドラッグにより、テキストが選択されるか、画像がドラッグアンドドロップされます。 UWPブラウザーでは、18が無効になり、17が有効になります。 両方とも、別々のプロパティを介してオプトインする必要があります。

@lukasf

私は個人的にブラウザでミドルクリックスクロールを時々使用します。左クリック+ドラッグにより、テキストが選択されるか、画像がドラッグアンドドロップされます。

テキストの選択などが機能しなくなるのを避ける必要があるのは良い点です。 この考えられる解決策についてどう思いますか。厄介な17モードを開始する代わりに、中クリックでマウスベースのパンモード(18)を開始します。

他のアプリの機能を見ると、一部のアプリでは、スペースバーキーを押しながらスクロール可能なコンテンツ領域を左クリックすることで、マウスベースのパンを開始できます。 このソリューションでは、パンモードはスペースバーとクリックでのみ開始されるため、スクロール可能なコンテンツ領域内で左クリックを正常に操作できます。 スペースバー+クリックによるパンは非常に快適で便利で高速です。

ただし、このスペースバー+クリックソリューションは、スクロール可能なコンテンツ領域内に編集可能なテキストボックスを表示する必要がないアプリに実装する方が簡単です。 編集可能なテキストボックスがスクロール可能なコンテンツ領域に存在する場合、パン機能によってユーザーがテキストボックスにスペースを入力できなくなることが問題になります。 したがって、あなたが言ったように、この機能はプロパティを介してオプトインする必要があります。 または、スペースバーを使用せずに、中クリックでマウスベースのパンモードを開始します(18)。これにより、ユーザーがテキストボックスにスペースを入力できないという問題が解消されます。

@verelpode
すべてのブラウザと、モード17をサポートする他の多くのアプリケーション(Word、Adobe Reader、Outlookなど)を使用して、これを実装する必要があると思います。 あなたが個人的にそれを厄介だと思ったからといって、それが他の人にとって役に立たないという意味ではありません。 もちろん、両方のモードをオプトインする必要があります。そうすれば、開発者はアプリで何を使用するかを決定できます。 これにより、アプリにとって意味がある場合は、スペースバーとクリックの動作も可能になります。スペースバーを下にするとモード18を有効にし、スペースバーを上にすると再び無効にします。

@ lukasf-わかりました、いいですね。 パンモード(18)でテキストの選択や画像のドラッグアンドドロップなどが妨げられない場合は、モード17の使用を停止して18に切り替えると思いましたが、実際には両方のモードでサポートされます。

@verelpode@lukasfのフィードバックに感謝します。最終的には、Scrollerコントロールのパブリックノブで番号17と18をオン/オフにすることに同意します。17 =マウスベースの一定速度パンと呼びましょう。 18 =マウスベースのパン。

私が行った調査作業を追加するために、PRhttps ://github.com/microsoft/microsoft-ui-xaml/pull/1472を送信しました。 今日のスクローラーを使用して、17と18の両方をサポートすることにどれだけ近づくことができるかを知りたかったのです。

タッチベースやマウスホイールベースのエクスペリエンスとは異なり、ソリューションは100%UIスレッドにバインドされていますが、18 =マウスベースのパンでは問題はありませんでした。 マウスのPointerMovedイベントをリッスンしながらScrollToメソッドを使用しました。 最終的には、基盤となるInteractionTrackerコンポーネントで、指の動きと同じようにマウスの動きを処理する必要があります。

17 =マウスベースの一定速度パン(私が個人的に嫌いな経験)の場合、物事ははるかにトリッキーです。 プロトタイプは理想からほど遠いので、すべての問題に対処しようとはしませんでしたが、特に2つが懸念しています。

  • 一定速度のパン(つまり、0速度の減衰のパン)中に、現在のScrollerで、古い位置にジャンプせずに移動を停止する方法はないと思います(ScrollBy(0、0)を使用) 。 構成スレッドがUIスレッドよりどれだけ進んでいるかを知ることは確実に不可能です。 そのため、グリッチのない方法で速度を停止するには、いくつかの新しいパブリックScrollerAPIが必要になります。
  • マウスのPointerReleasedイベントの後、マウスのキャプチャを維持できませんでした。 これを実現するには、新しいXamlフレームワーク機能が必要になるようです。
    とにかく、これは、基盤となるInteractionTrackerでエクスペリエンスの一部を直接処理する必要がある別のケースである可能性があります。
    将来のScroller / InteractionTracker機能について説明するときは、これらを確実に念頭に置いておくつもりです。

@RBrid

18 =マウスベースのパンでは、状況はかなりうまくいきました…...
17 =マウスベースの一定速度パン(私が個人的に嫌いな経験)の場合、物事ははるかにトリッキーです。

面白い結果! その場合、17 =一定速度の難しさを考慮し、左クリックの通常の使用を妨げない方法で18を実装できることを考慮すると、私の個人的な意見では、提案はおそらく次のように更新する必要があると思います。 17を放棄し、代わりに18をサポートしますが、確かに、17 =一定速度が放棄された場合に何人のユーザーが文句を言うかはわかりません。

これらの調査をありがとう@RBrid 。 モード18がすでに機能していると聞いてうれしいです! UIスレッドのロード中でもスムーズな操作を可能にするために、InteractionTrackerで処理するのが理想的であることに同意します。

@verelpode両方のモードが「Should」に設定されています。 したがって、努力が高すぎてモード17を実現できない場合は、省略しておくことができます(必要に応じて、後で追加することもできます)。 しかし、多分誰かがあまり多くの変更なしでそれを実現する方法を見つけるでしょう。

新しいScrollViewerに「Ctrl」キーでズームを無効化またはカスタマイズする機能があることを願っています。

このページは役に立ちましたか?
0 / 5 - 0 評価