harmonyos-best-practices-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +121 -0
- package/data/docs/bpta-2in1-window-shape.md +296 -0
- package/data/docs/bpta-abckitts-implements-instrumentation.md +1279 -0
- package/data/docs/bpta-add-watermark.md +379 -0
- package/data/docs/bpta-ads-jump.md +67 -0
- package/data/docs/bpta-agent.md +472 -0
- package/data/docs/bpta-always-on-market-watch.md +703 -0
- package/data/docs/bpta-analysis-of-image-blurring.md +231 -0
- package/data/docs/bpta-analyze-memory-problem.md +17 -0
- package/data/docs/bpta-animation-frame.md +28 -0
- package/data/docs/bpta-antipeep-protection.md +291 -0
- package/data/docs/bpta-app-architecture-overview.md +25 -0
- package/data/docs/bpta-app-asset-protection-design.md +277 -0
- package/data/docs/bpta-app-code-ob.md +180 -0
- package/data/docs/bpta-app-concurrency-design.md +1189 -0
- package/data/docs/bpta-app-data-security.md +397 -0
- package/data/docs/bpta-app-icon-configuration.md +226 -0
- package/data/docs/bpta-app-privacy-protection.md +295 -0
- package/data/docs/bpta-application-aspect-programming-design.md +675 -0
- package/data/docs/bpta-application-cold-start-optimization.md +1397 -0
- package/data/docs/bpta-application-continue-progess.md +285 -0
- package/data/docs/bpta-application-gesture-share.md +468 -0
- package/data/docs/bpta-application-knock-file-share.md +263 -0
- package/data/docs/bpta-application-knock-video-share.md +552 -0
- package/data/docs/bpta-application-latency-optimization-cases.md +615 -0
- package/data/docs/bpta-application-power-analysis.md +15 -0
- package/data/docs/bpta-application-power-optimization.md +12 -0
- package/data/docs/bpta-application-power-test.md +52 -0
- package/data/docs/bpta-application-track-practice.md +595 -0
- package/data/docs/bpta-arkts-high-performance.md +464 -0
- package/data/docs/bpta-arkts-js-memory-analysis.md +111 -0
- package/data/docs/bpta-arkts-language.md +18 -0
- package/data/docs/bpta-arkweb-component-security.md +1134 -0
- package/data/docs/bpta-arkweb_rendering_framework.md +412 -0
- package/data/docs/bpta-aspect-implements-aop.md +505 -0
- package/data/docs/bpta-audio-and-video.md +30 -0
- package/data/docs/bpta-audio-cast.md +460 -0
- package/data/docs/bpta-audio-focus-management.md +862 -0
- package/data/docs/bpta-audio-in-ear-monitor.md +803 -0
- package/data/docs/bpta-audio-playback-series.md +16 -0
- package/data/docs/bpta-audio-record-base-on-audiocapturer.md +188 -0
- package/data/docs/bpta-audio-record-base-on-avrecorder-arkts.md +179 -0
- package/data/docs/bpta-audio-record-base-on-avrecorder.md +207 -0
- package/data/docs/bpta-audio-record-base-on-avscreencapture.md +165 -0
- package/data/docs/bpta-audio-record-base-on-ohaudio.md +162 -0
- package/data/docs/bpta-audio-record-overview.md +34 -0
- package/data/docs/bpta-audio-record.md +16 -0
- package/data/docs/bpta-audio-ripple-animation.md +198 -0
- package/data/docs/bpta-audio-video-synchronization.md +508 -0
- package/data/docs/bpta-audio-video.md +15 -0
- package/data/docs/bpta-automated-testing-frameworks.md +481 -0
- package/data/docs/bpta-avplayer-basic-control.md +533 -0
- package/data/docs/bpta-avplayer-embeded-network-video.md +486 -0
- package/data/docs/bpta-avplayer-embeded-short-video.md +512 -0
- package/data/docs/bpta-avplayer-long-video.md +907 -0
- package/data/docs/bpta-avplayer-short-video.md +158 -0
- package/data/docs/bpta-avplayer-video-practices.md +15 -0
- package/data/docs/bpta-avscreencapture-for-screen-recording.md +1121 -0
- package/data/docs/bpta-back-task-implement.md +317 -0
- package/data/docs/bpta-background-blur.md +316 -0
- package/data/docs/bpta-background-sensors-baned-analysis.md +93 -0
- package/data/docs/bpta-best-practices-long-list.md +891 -0
- package/data/docs/bpta-best-practices-overview.md +48 -0
- package/data/docs/bpta-bluetooth-low-energy.md +905 -0
- package/data/docs/bpta-buffer-mode-transcoding.md +728 -0
- package/data/docs/bpta-buffer-power-optimization.md +224 -0
- package/data/docs/bpta-camera-shot2see.md +368 -0
- package/data/docs/bpta-card-update-and-data-interaction.md +670 -0
- package/data/docs/bpta-carousel-graphic-works.md +379 -0
- package/data/docs/bpta-cell-phone.md +13 -0
- package/data/docs/bpta-click-to-click-response-optimization.md +264 -0
- package/data/docs/bpta-click-to-complete-delay-analysis.md +637 -0
- package/data/docs/bpta-collaboration-office.md +1178 -0
- package/data/docs/bpta-comment-reply-pop-up-window.md +523 -0
- package/data/docs/bpta-common-list-flows.md +688 -0
- package/data/docs/bpta-common-list-operations.md +828 -0
- package/data/docs/bpta-common-network-query.md +784 -0
- package/data/docs/bpta-comparative_practice_of_taskpool_and_worker.md +381 -0
- package/data/docs/bpta-compatible-scheme.md +11 -0
- package/data/docs/bpta-complex-type-pass.md +868 -0
- package/data/docs/bpta-component-nesting-optimization.md +421 -0
- package/data/docs/bpta-component-reuse-issue-diagnosis-and-analysis.md +637 -0
- package/data/docs/bpta-component-reuse.md +1258 -0
- package/data/docs/bpta-concurrency-capability.md +23 -0
- package/data/docs/bpta-concurrent-optimization.md +369 -0
- package/data/docs/bpta-content-creation.md +646 -0
- package/data/docs/bpta-continue-cast.md +702 -0
- package/data/docs/bpta-continue-data.md +335 -0
- package/data/docs/bpta-continue.md +1323 -0
- package/data/docs/bpta-control-rendering-range.md +29 -0
- package/data/docs/bpta-controlling-background-process-cpu.md +31 -0
- package/data/docs/bpta-crash-monitor-practice.md +116 -0
- package/data/docs/bpta-cross-domain-solutions-for-web-pages.md +308 -0
- package/data/docs/bpta-cross-end-migration.md +13 -0
- package/data/docs/bpta-cross-module-reference.md +406 -0
- package/data/docs/bpta-cross-platform-compatibility.md +321 -0
- package/data/docs/bpta-custom-camera-photo.md +454 -0
- package/data/docs/bpta-custom-camera-preview.md +1170 -0
- package/data/docs/bpta-custom-camera-video.md +322 -0
- package/data/docs/bpta-custom-font-settings.md +354 -0
- package/data/docs/bpta-custom-hvigor-plugin.md +159 -0
- package/data/docs/bpta-custom-keyboard.md +519 -0
- package/data/docs/bpta-customdialog-selection-and-development.md +406 -0
- package/data/docs/bpta-dark-mode-adaptation.md +321 -0
- package/data/docs/bpta-deal-stride-solution.md +261 -0
- package/data/docs/bpta-decrease_pakage_size.md +126 -0
- package/data/docs/bpta-delayed-trigger-operation.md +215 -0
- package/data/docs/bpta-desktop-shortcuts.md +180 -0
- package/data/docs/bpta-detection.md +12 -0
- package/data/docs/bpta-developing-high-performance-ui.md +19 -0
- package/data/docs/bpta-development-scenarios-for-tabs.md +934 -0
- package/data/docs/bpta-dialog-encapsulation.md +201 -0
- package/data/docs/bpta-dispose-highly-loaded-component-render.md +352 -0
- package/data/docs/bpta-distribute-drag-cast.md +60 -0
- package/data/docs/bpta-distributed-pasteboard-cast.md +88 -0
- package/data/docs/bpta-distributed-pasteboard.md +314 -0
- package/data/docs/bpta-drawing-capability-improve-performance.md +436 -0
- package/data/docs/bpta-dynamic-link-library.md +272 -0
- package/data/docs/bpta-easygo-parallel.md +402 -0
- package/data/docs/bpta-fair-use-animation.md +1693 -0
- package/data/docs/bpta-file-transmission-based-on-sfft.md +265 -0
- package/data/docs/bpta-file-upload-and-download-performance.md +484 -0
- package/data/docs/bpta-foldable-guide.md +205 -0
- package/data/docs/bpta-folded-hover.md +202 -0
- package/data/docs/bpta-form-kit.md +12 -0
- package/data/docs/bpta-frontend-invisible-animation-analysis.md +187 -0
- package/data/docs/bpta-full-scenario-collaborative-development.md +13 -0
- package/data/docs/bpta-fuzzy-scene-performance-optimization.md +256 -0
- package/data/docs/bpta-game-prelaunch-practice.md +175 -0
- package/data/docs/bpta-general-comments.md +17 -0
- package/data/docs/bpta-gestures-practice.md +619 -0
- package/data/docs/bpta-global-state-management-state-store.md +472 -0
- package/data/docs/bpta-gpu-acceleration-practices.md +11 -0
- package/data/docs/bpta-graphic-drawing-practices.md +13 -0
- package/data/docs/bpta-grid-based-on-scrollcomponents.md +1112 -0
- package/data/docs/bpta-grid-drag-swap.md +725 -0
- package/data/docs/bpta-hadss_dialoghub.md +786 -0
- package/data/docs/bpta-harmony-application-security.md +1253 -0
- package/data/docs/bpta-hdrtosdr.md +439 -0
- package/data/docs/bpta-hdrvivid.md +700 -0
- package/data/docs/bpta-high-cpu-load-analysis.md +113 -0
- package/data/docs/bpta-high-performance-json-parsing.md +263 -0
- package/data/docs/bpta-high-performance-protobuf-parsing.md +259 -0
- package/data/docs/bpta-hmos-live-stream-audio-call.md +140 -0
- package/data/docs/bpta-hmos-live-stream-solution.md +495 -0
- package/data/docs/bpta-hmrouter.md +659 -0
- package/data/docs/bpta-hopping.md +60 -0
- package/data/docs/bpta-hwc-self-rendering-layer-analysis.md +77 -0
- package/data/docs/bpta-image-processing-practices.md +13 -0
- package/data/docs/bpta-image-to-video-synthesis.md +459 -0
- package/data/docs/bpta-image-white-lump-solution.md +282 -0
- package/data/docs/bpta-image_get_and_save.md +120 -0
- package/data/docs/bpta-implement-timeline-based-on-canvas.md +493 -0
- package/data/docs/bpta-implementing-image-filters.md +406 -0
- package/data/docs/bpta-implementing-image-resizable.md +270 -0
- package/data/docs/bpta-improve-layout-performance.md +547 -0
- package/data/docs/bpta-improve-running-efficiency.md +187 -0
- package/data/docs/bpta-improve_grid_performance.md +268 -0
- package/data/docs/bpta-input-method-framework.md +12 -0
- package/data/docs/bpta-intent-recommend-practice.md +313 -0
- package/data/docs/bpta-js-leak-watcher.md +153 -0
- package/data/docs/bpta-kernel-memory-analysis.md +38 -0
- package/data/docs/bpta-keyboard-layout-adapt.md +725 -0
- package/data/docs/bpta-landscape-and-portrait-development.md +947 -0
- package/data/docs/bpta-layered-architecture-design.md +82 -0
- package/data/docs/bpta-lazyforeach-optimization.md +217 -0
- package/data/docs/bpta-link-between-apps-overview.md +99 -0
- package/data/docs/bpta-list-based-on-scrollcomponents.md +1643 -0
- package/data/docs/bpta-lite-wearable-guide.md +1899 -0
- package/data/docs/bpta-live-form-development-practice.md +544 -0
- package/data/docs/bpta-live-streaming-optimization.md +397 -0
- package/data/docs/bpta-local-file-and-data-multithreaded-io.md +367 -0
- package/data/docs/bpta-local-file.md +11 -0
- package/data/docs/bpta-lock-screen-immersive-live-window.md +473 -0
- package/data/docs/bpta-long-snapshot-practice.md +1046 -0
- package/data/docs/bpta-low-power-consumption-of-background-tasks.md +14 -0
- package/data/docs/bpta-low-power-consumption-of-foreground-tasks.md +14 -0
- package/data/docs/bpta-low-power-design-in-dark-mode.md +418 -0
- package/data/docs/bpta-ltpo-description.md +323 -0
- package/data/docs/bpta-maleoon-gpu-best-practices.md +1297 -0
- package/data/docs/bpta-malloc-dispatch-table.md +144 -0
- package/data/docs/bpta-managing-audio-input-devices.md +350 -0
- package/data/docs/bpta-managing-audio-output-devices.md +399 -0
- package/data/docs/bpta-mate-book-fold.md +229 -0
- package/data/docs/bpta-matetv-guide.md +223 -0
- package/data/docs/bpta-matext-guide.md +269 -0
- package/data/docs/bpta-memory-basic-knowledge.md +71 -0
- package/data/docs/bpta-memory-optimization.md +545 -0
- package/data/docs/bpta-modular-design.md +282 -0
- package/data/docs/bpta-multi-device-adaptive-layout.md +775 -0
- package/data/docs/bpta-multi-device-adaptive.md +11 -0
- package/data/docs/bpta-multi-device-camera.md +584 -0
- package/data/docs/bpta-multi-device-collaboration.md +19 -0
- package/data/docs/bpta-multi-device-component-layout.md +190 -0
- package/data/docs/bpta-multi-device-design-principles.md +26 -0
- package/data/docs/bpta-multi-device-function.md +99 -0
- package/data/docs/bpta-multi-device-hardware.md +12 -0
- package/data/docs/bpta-multi-device-ide.md +124 -0
- package/data/docs/bpta-multi-device-interaction.md +11 -0
- package/data/docs/bpta-multi-device-layout-overview.md +47 -0
- package/data/docs/bpta-multi-device-overview.md +340 -0
- package/data/docs/bpta-multi-device-page-layout.md +699 -0
- package/data/docs/bpta-multi-device-page.md +19 -0
- package/data/docs/bpta-multi-device-resource.md +122 -0
- package/data/docs/bpta-multi-device-responsive-layout.md +1274 -0
- package/data/docs/bpta-multi-device-responsive.md +14 -0
- package/data/docs/bpta-multi-device-screen-diff.md +197 -0
- package/data/docs/bpta-multi-device-screen-layout.md +834 -0
- package/data/docs/bpta-multi-device-start.md +376 -0
- package/data/docs/bpta-multi-device-ui-development.md +27 -0
- package/data/docs/bpta-multi-device-window-direction.md +1322 -0
- package/data/docs/bpta-multi-device-window-immersive.md +364 -0
- package/data/docs/bpta-multi-device-window-mode.md +1293 -0
- package/data/docs/bpta-multi-device-window.md +13 -0
- package/data/docs/bpta-multi-device.md +13 -0
- package/data/docs/bpta-multi-interaction.md +368 -0
- package/data/docs/bpta-multi-mobile-payment.md +282 -0
- package/data/docs/bpta-multi-music-app-overview.md +365 -0
- package/data/docs/bpta-multi-settings-application-page.md +163 -0
- package/data/docs/bpta-multi-tab-practice.md +750 -0
- package/data/docs/bpta-multi-target.md +490 -0
- package/data/docs/bpta-multi-window-practice.md +795 -0
- package/data/docs/bpta-multi_game.md +472 -0
- package/data/docs/bpta-music-card.md +1916 -0
- package/data/docs/bpta-music-playback-scenarios.md +120 -0
- package/data/docs/bpta-native-memory-analysis.md +101 -0
- package/data/docs/bpta-native-sub-main-comm.md +323 -0
- package/data/docs/bpta-navigation-scenarios.md +69 -0
- package/data/docs/bpta-network-ca-security.md +241 -0
- package/data/docs/bpta-network-reconnection.md +327 -0
- package/data/docs/bpta-network-resources.md +24 -0
- package/data/docs/bpta-news-reading.md +12 -0
- package/data/docs/bpta-news_homepage.md +449 -0
- package/data/docs/bpta-object-serialization-performance.md +12 -0
- package/data/docs/bpta-one-shot-to-the-end.md +932 -0
- package/data/docs/bpta-online-video-playback-lags-practice.md +298 -0
- package/data/docs/bpta-optimization-overview.md +227 -0
- package/data/docs/bpta-optimization-tool-practice.md +20 -0
- package/data/docs/bpta-package-structure.md +13 -0
- package/data/docs/bpta-pad-guide.md +268 -0
- package/data/docs/bpta-page-brightness-settings.md +256 -0
- package/data/docs/bpta-page-transition.md +583 -0
- package/data/docs/bpta-pc-guide.md +438 -0
- package/data/docs/bpta-pc.md +12 -0
- package/data/docs/bpta-perceived-smoothness.md +49 -0
- package/data/docs/bpta-performance-detection.md +160 -0
- package/data/docs/bpta-performance-guide-reading.md +50 -0
- package/data/docs/bpta-performance-mainthread-consumption-detection.md +11 -0
- package/data/docs/bpta-performance-optimization.md +23 -0
- package/data/docs/bpta-performance-runtime-detection.md +13 -0
- package/data/docs/bpta-performance-sliding-frame-drop-detection.md +19 -0
- package/data/docs/bpta-performance-startup-time-detection.md +13 -0
- package/data/docs/bpta-permission-application.md +318 -0
- package/data/docs/bpta-permission-timeout-analysis.md +51 -0
- package/data/docs/bpta-photo.md +15 -0
- package/data/docs/bpta-picture-preview.md +464 -0
- package/data/docs/bpta-picture.md +12 -0
- package/data/docs/bpta-playing-formatted-audio-based-avplayer-arkts.md +481 -0
- package/data/docs/bpta-playing-formatted-audio-based-avplayer-cpp.md +593 -0
- package/data/docs/bpta-playing-pcm-audio-based-audiorenderer.md +959 -0
- package/data/docs/bpta-playing-pcm-audio-based-ohaudio.md +599 -0
- package/data/docs/bpta-playing-short-audio-based-soundpool.md +182 -0
- package/data/docs/bpta-positioning.md +364 -0
- package/data/docs/bpta-power-basic-quality-test.md +35 -0
- package/data/docs/bpta-power-consumption-analysis.md +12 -0
- package/data/docs/bpta-power-consumption-develop-analysis.md +12 -0
- package/data/docs/bpta-power-consumption-experience.md +119 -0
- package/data/docs/bpta-power-consumption-runtime-analysis.md +15 -0
- package/data/docs/bpta-power_overview.md +26 -0
- package/data/docs/bpta-pptimized-component-drawing.md +27 -0
- package/data/docs/bpta-pre-connect.md +133 -0
- package/data/docs/bpta-preloading-resources.md +21 -0
- package/data/docs/bpta-program-framework.md +15 -0
- package/data/docs/bpta-properly-use-foreground-resources.md +22 -0
- package/data/docs/bpta-purax-guide.md +215 -0
- package/data/docs/bpta-quality-overview.md +79 -0
- package/data/docs/bpta-reader-page-flip.md +890 -0
- package/data/docs/bpta-reasonable-audio-playback-use.md +42 -0
- package/data/docs/bpta-reasonable-audio-use.md +163 -0
- package/data/docs/bpta-reasonable-bluetooth-use.md +52 -0
- package/data/docs/bpta-reasonable-gps-use.md +59 -0
- package/data/docs/bpta-reasonable-network-use.md +105 -0
- package/data/docs/bpta-reasonable-position-navigation-use.md +47 -0
- package/data/docs/bpta-reasonable-request-use.md +77 -0
- package/data/docs/bpta-reasonable-sensor-use.md +53 -0
- package/data/docs/bpta-reasonable-system-use.md +67 -0
- package/data/docs/bpta-recommended-use-of-device-id.md +79 -0
- package/data/docs/bpta-reduce-layout-nodes.md +30 -0
- package/data/docs/bpta-reduce-time-consuming.md +36 -0
- package/data/docs/bpta-redundancy-refresh-guide.md +409 -0
- package/data/docs/bpta-render-web-using-same-layer-render.md +601 -0
- package/data/docs/bpta-resource-and-storage-optimization.md +14 -0
- package/data/docs/bpta-retrieve-process-memory-info.md +49 -0
- package/data/docs/bpta-rich-text-display.md +475 -0
- package/data/docs/bpta-rich-text-editor.md +426 -0
- package/data/docs/bpta-risk-control-engine.md +146 -0
- package/data/docs/bpta-scenario-performance-optimization.md +17 -0
- package/data/docs/bpta-scenario-power-optimization.md +12 -0
- package/data/docs/bpta-scenario-stability-address-sanitizer.md +210 -0
- package/data/docs/bpta-scenario-stability-app-freeze.md +615 -0
- package/data/docs/bpta-scenario-stability-cppcrash.md +516 -0
- package/data/docs/bpta-scenario-stability-exception-exit.md +12 -0
- package/data/docs/bpta-scenario-stability-jscrash.md +922 -0
- package/data/docs/bpta-scenario-stability-leak.md +276 -0
- package/data/docs/bpta-scenario-stability.md +14 -0
- package/data/docs/bpta-screen-flicker-solution.md +480 -0
- package/data/docs/bpta-shared-bicycle.md +509 -0
- package/data/docs/bpta-short-video-base-adaptivevideo.md +403 -0
- package/data/docs/bpta-smart-reach.md +306 -0
- package/data/docs/bpta-smartwatch.md +755 -0
- package/data/docs/bpta-smartwatchnavigation.md +384 -0
- package/data/docs/bpta-smooth-application-design.md +225 -0
- package/data/docs/bpta-smooth-switching.md +294 -0
- package/data/docs/bpta-social-communications.md +11 -0
- package/data/docs/bpta-social-share.md +637 -0
- package/data/docs/bpta-solutions-to-special-issues.md +12 -0
- package/data/docs/bpta-sound-quality-switching.md +422 -0
- package/data/docs/bpta-spatiality-immersive.md +531 -0
- package/data/docs/bpta-special-text-recognition.md +137 -0
- package/data/docs/bpta-stability-address-illegal-way.md +190 -0
- package/data/docs/bpta-stability-address-sanitizer-catagory.md +212 -0
- package/data/docs/bpta-stability-address-sanitizer-faq.md +32 -0
- package/data/docs/bpta-stability-address-sanitizer-opt.md +170 -0
- package/data/docs/bpta-stability-address-sanitizer-overview.md +23 -0
- package/data/docs/bpta-stability-address-sanitizer-principle.md +179 -0
- package/data/docs/bpta-stability-analysis.md +17 -0
- package/data/docs/bpta-stability-app-analyzer.md +11 -0
- package/data/docs/bpta-stability-app-crash-cpp-way.md +200 -0
- package/data/docs/bpta-stability-app-crash-js-way.md +148 -0
- package/data/docs/bpta-stability-app-crash.md +13 -0
- package/data/docs/bpta-stability-app-freeze-ark-runtime.md +339 -0
- package/data/docs/bpta-stability-app-freeze-opt.md +80 -0
- package/data/docs/bpta-stability-app-freeze-way.md +410 -0
- package/data/docs/bpta-stability-app-freeze.md +12 -0
- package/data/docs/bpta-stability-app-killed-way.md +49 -0
- package/data/docs/bpta-stability-ark-detection.md +12 -0
- package/data/docs/bpta-stability-ark-exception-detection.md +38 -0
- package/data/docs/bpta-stability-ark-runtime-detection.md +134 -0
- package/data/docs/bpta-stability-asan-detection.md +450 -0
- package/data/docs/bpta-stability-coding-standard-api.md +2054 -0
- package/data/docs/bpta-stability-coding-standard-cpp.md +91 -0
- package/data/docs/bpta-stability-coding-standard-libuv.md +772 -0
- package/data/docs/bpta-stability-coding-standard-ndk-arkts.md +189 -0
- package/data/docs/bpta-stability-coding-standard-node.md +478 -0
- package/data/docs/bpta-stability-coding-standard.md +16 -0
- package/data/docs/bpta-stability-cpp-crash-opt.md +346 -0
- package/data/docs/bpta-stability-detection.md +14 -0
- package/data/docs/bpta-stability-deveco-testing.md +73 -0
- package/data/docs/bpta-stability-develop-detection.md +17 -0
- package/data/docs/bpta-stability-exception-exit-opt.md +12 -0
- package/data/docs/bpta-stability-fault-log.md +14 -0
- package/data/docs/bpta-stability-fault-type.md +31 -0
- package/data/docs/bpta-stability-file-handle-detection.md +96 -0
- package/data/docs/bpta-stability-gwpasan-detection.md +588 -0
- package/data/docs/bpta-stability-hwasan-detection.md +360 -0
- package/data/docs/bpta-stability-ide-static-detection.md +343 -0
- package/data/docs/bpta-stability-js-crash-opt.md +21 -0
- package/data/docs/bpta-stability-js-memleak-detection.md +214 -0
- package/data/docs/bpta-stability-leak-detection.md +15 -0
- package/data/docs/bpta-stability-leak-opt.md +251 -0
- package/data/docs/bpta-stability-leak-way.md +459 -0
- package/data/docs/bpta-stability-log-specs.md +31 -0
- package/data/docs/bpta-stability-log-standard-hilog.md +191 -0
- package/data/docs/bpta-stability-log-standard.md +11 -0
- package/data/docs/bpta-stability-memleak-detection-overview.md +109 -0
- package/data/docs/bpta-stability-native-memleak-detection.md +204 -0
- package/data/docs/bpta-stability-operate-apm.md +113 -0
- package/data/docs/bpta-stability-operate-app-event.md +320 -0
- package/data/docs/bpta-stability-operate-event.md +11 -0
- package/data/docs/bpta-stability-operate.md +15 -0
- package/data/docs/bpta-stability-opt.md +18 -0
- package/data/docs/bpta-stability-overview.md +17 -0
- package/data/docs/bpta-stability-ram-detection.md +17 -0
- package/data/docs/bpta-stability-runtime-address-sanitizer-detection.md +21 -0
- package/data/docs/bpta-stability-runtime-appkilled-detection.md +44 -0
- package/data/docs/bpta-stability-runtime-crash-detection.md +14 -0
- package/data/docs/bpta-stability-runtime-detection.md +14 -0
- package/data/docs/bpta-stability-runtime-exception-exit-detection.md +12 -0
- package/data/docs/bpta-stability-runtime-freeze-detection.md +21 -0
- package/data/docs/bpta-stability-runtime-leak-detection.md +31 -0
- package/data/docs/bpta-stability-testing.md +11 -0
- package/data/docs/bpta-stability-thread-detection.md +11 -0
- package/data/docs/bpta-stability-thread-leak-detection.md +35 -0
- package/data/docs/bpta-stability-tsan-detection.md +477 -0
- package/data/docs/bpta-stability-ubsan-detection.md +350 -0
- package/data/docs/bpta-startup-response-optimization.md +12 -0
- package/data/docs/bpta-state-refresh.md +48 -0
- package/data/docs/bpta-static-scenarios.md +63 -0
- package/data/docs/bpta-status-management.md +872 -0
- package/data/docs/bpta-surface-encoder.md +427 -0
- package/data/docs/bpta-swiper_high_performance_development_guide.md +357 -0
- package/data/docs/bpta-tablet-pc.md +11 -0
- package/data/docs/bpta-taskpool_usage_specifications_and_faqs.md +625 -0
- package/data/docs/bpta-text-expand-collapse.md +274 -0
- package/data/docs/bpta-texture-compression-improve-performance.md +336 -0
- package/data/docs/bpta-thread-priority-setting.md +233 -0
- package/data/docs/bpta-threads-serialization-timeout-analysis.md +169 -0
- package/data/docs/bpta-time-optimization-of-the-main-thread.md +1239 -0
- package/data/docs/bpta-travel-navigation.md +11 -0
- package/data/docs/bpta-tv.md +11 -0
- package/data/docs/bpta-ui-component-encapsulation.md +585 -0
- package/data/docs/bpta-ui-component-performance-optimization.md +597 -0
- package/data/docs/bpta-ui-dynamic-operations.md +618 -0
- package/data/docs/bpta-ui-skip-analysis.md +191 -0
- package/data/docs/bpta-unified-drag-and-drop.md +1189 -0
- package/data/docs/bpta-use-of-background-hardware-resources.md +16 -0
- package/data/docs/bpta-use-of-background-software-resources.md +14 -0
- package/data/docs/bpta-use-of-background-tasks.md +23 -0
- package/data/docs/bpta-utilize-hwc-efficiently.md +461 -0
- package/data/docs/bpta-vdeocast.md +558 -0
- package/data/docs/bpta-video-adaptation-based-web.md +462 -0
- package/data/docs/bpta-video-barrage.md +68 -0
- package/data/docs/bpta-video-codec.md +42 -0
- package/data/docs/bpta-video-component-long-video.md +659 -0
- package/data/docs/bpta-video-component-short-video.md +337 -0
- package/data/docs/bpta-video-layer.md +32 -0
- package/data/docs/bpta-video-practices.md +12 -0
- package/data/docs/bpta-video-render.md +1225 -0
- package/data/docs/bpta-video-rom.md +37 -0
- package/data/docs/bpta-video-thumbnail.md +179 -0
- package/data/docs/bpta-video-wifi.md +40 -0
- package/data/docs/bpta-vsync-power-optimization.md +116 -0
- package/data/docs/bpta-waterflow-based-on-scrollcomponents.md +989 -0
- package/data/docs/bpta-waterflow-operations.md +991 -0
- package/data/docs/bpta-waterflow-performance-optimization.md +191 -0
- package/data/docs/bpta-wavewheel-for-image-editor.md +421 -0
- package/data/docs/bpta-wear.md +12 -0
- package/data/docs/bpta-web-adaptation.md +451 -0
- package/data/docs/bpta-web-app-jump-and-pull-up.md +310 -0
- package/data/docs/bpta-web-click-response-delay-analysis.md +164 -0
- package/data/docs/bpta-web-completion-delay-analysis.md +209 -0
- package/data/docs/bpta-web-develop-optimization.md +2596 -0
- package/data/docs/bpta-web-development.md +15 -0
- package/data/docs/bpta-web-frame-rate-performance-analysis.md +252 -0
- package/data/docs/bpta-web-interceptor.md +724 -0
- package/data/docs/bpta-web-performance-optimization.md +11 -0
- package/data/docs/bpta-window-and-screen-management.md +12 -0
- package/data/docs/bpta-zhenlv.md +559 -0
- package/data/docs/changelog.md +1410 -0
- package/data/docs/low-power-consumption-suggestions.md +246 -0
- package/data/docs/multi-business-office.md +275 -0
- package/data/docs/multi-communication-app.md +240 -0
- package/data/docs/multi-community-app.md +257 -0
- package/data/docs/multi-convenient-life.md +501 -0
- package/data/docs/multi-financial-app.md +288 -0
- package/data/docs/multi-news-read.md +286 -0
- package/data/docs/multi-picture-app.md +219 -0
- package/data/docs/multi-shopping-price-comparison.md +254 -0
- package/data/docs/multi-short-video-app.md +315 -0
- package/data/docs/multi-ticket-class.md +458 -0
- package/data/docs/multi-travel-accommodation.md +361 -0
- package/data/docs/multi-travel-navigation.md +449 -0
- package/data/docs/multi-video-app.md +492 -0
- package/data/index.md +2886 -0
- package/dist/data.js +180 -0
- package/dist/index.js +203 -0
- package/dist/search.js +102 -0
- package/package.json +57 -0
- package/scripts/trim-code-extra.mjs +78 -0
- package/scripts/trim-code.mjs +106 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# 分析任务执行超时问题
|
|
2
|
+
|
|
3
|
+
> 来源: https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-permission-timeout-analysis
|
|
4
|
+
> 文档标识(fileName): bpta-permission-timeout-analysis
|
|
5
|
+
> 目录(catalogName): best-practices
|
|
6
|
+
> 语言: cn
|
|
7
|
+
> 更新时间: 2026-06-23 03:39:35
|
|
8
|
+
> 导航地址: /hmos/hmos-dp1
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
在应用开发过程中,开发者希望某段业务逻辑能在预期时间内完成执行。如果该业务逻辑的执行时间超过了预期,即被视为任务超时。
|
|
12
|
+
|
|
13
|
+
任务超时检测包括主线程超时检测和任务执行超时检测,这两种检测均可通过HiCollie实现,以自定义时长对选定的业务逻辑进行主动监控。对于主线程超时,也可以选择使用默认时长进行检测。详情请参阅:[HiCollie使用指导](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/hicollie)。
|
|
14
|
+
|
|
15
|
+
任务执行超时检测的原理、日志获取方式及规格,请参阅:[任务超时检测](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/apptask-timeout-guidelines)。
|
|
16
|
+
|
|
17
|
+
#### 分析思路
|
|
18
|
+
|
|
19
|
+
1. 主线程超时
|
|
20
|
+
|
|
21
|
+
[主线程超时检测](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/apptask-timeout-guidelines#主线程超时检测)实际利用多次采样堆栈,并聚类的原理来提供最终堆栈。分析此类问题时,开发者只需关注与业务逻辑相关的堆栈(命中次数最高者),并进行优化即可。
|
|
22
|
+
2. 任务执行超时
|
|
23
|
+
|
|
24
|
+
由于任务执行超时分析方法与应用冻屏分析方法一致,可参考[应用冻屏(AppFreeze)问题排查方法](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-stability-app-freeze-way)。
|
|
25
|
+
|
|
26
|
+
#### 分析步骤
|
|
27
|
+
|
|
28
|
+
1. 示例:主线程超时采样堆栈,数字表示采样命中次数
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
9 #00 pc 0000757c /system/bin/appspawn(55679d09bcdea35bb1e0d4e1d9a3e58f)
|
|
32
|
+
9 #01 pc 000731c0 /system/lib/ld-musl-aarch64.so.1(add9e521e4eaf5cb009d4260f3b69ccd)
|
|
33
|
+
9 #02 pc 000090a9 /system/bin/appspawn(main+396)(55679d09bcdea35bb1e0d4e1d9a3e58f)
|
|
34
|
+
9 #03 pc 0000ab5d /system/bin/appspawn(AppSpawnRun+100)(55679d09bcdea35bb1e0d4e1d9a3e58f)
|
|
35
|
+
9 #04 pc 0000e7f1 /system/lib/chipset-pub-sdk/libbegetutil.z.so(RunLoop_+200)(52ace27d827ad482439bf32cc75bb17b)
|
|
36
|
+
......
|
|
37
|
+
9 #21 pc 00107aec /system/lib/ld-musl-aarch64.so.1(__pthread_cond_timedwait+628)(add9e521e4eaf5cb009d4260f3b69ccd)
|
|
38
|
+
1 #00 pc 00032e67 /system/lib/platformsdk/libmmi-util.z.so(OHOS::MMI::UDSSocket::OnReadPackets(OHOS::MMI::CircleStreamBuffer&, std::__h::function<void (OHOS::MMI::NetPacket&)>)+158)(99e56bc765f9208f7b7ba8b268886a59)
|
|
39
|
+
1 #01 pc 0000312e5 /system/lib/platformsdk/libmmi-client.z.so(OHOS::MMI::ClientMsgHandler::OnMsgHandler(OHOS::MMI::UDSClient const&, OHOS::MMI::NetPacket&)+340)(66ac85e964777ae89f0c26c339093cd1)
|
|
40
|
+
1 #02 pc 0003016b /system/lib/platformsdk/libmmi-client.z.so(OHOS::MMI::ClientMsgHandler::OnPointerEvent(OHOS::MMI::UDSClient const&, OHOS::MMI::NetPacket&)+1222)(66ac85e964777ae89f0c26c339093cd1)
|
|
41
|
+
1 #03 pc 0003b96b /system/lib/platformsdk/libmmi-client.z.so(OHOS::MMI::InputManagerImpl::OnPointerEvent(std::__h::shared_ptr<OHOS::MMI::PointerEvent>)+1370)(66ac85e964777ae89f0c26c339093cd1)
|
|
42
|
+
1 #04 pc 00095903 /system/lib/platformsdk/libwm.z.so(OHOS::Rosen::InputEventListener::OnInputEvent(std::__h::shared_ptr<OHOS::MMI::PointerEvent>) const+478)(9c40c5f416d6f830435126998fbcad42)
|
|
43
|
+
......
|
|
44
|
+
1 #21 pc 003f5c55 /system/lib/platformsdk/libark_jsruntime.so(4e6a2651ec80a7f639233f414d6486fe)
|
|
45
|
+
1 #22 at anonymous (/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/Index.js:67:17)
|
|
46
|
+
1 #23 at wait2 (/entry/build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/Index.js:16:12)
|
|
47
|
+
......
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
如上述示例所示,通过订阅相关事件获取日志信息后,按照#xx前的数字排查,排除系统侧堆栈之后,查找与业务逻辑相关的堆栈,数字越高表示采样栈命中次数越高,需要优化的可能性越大。如上述案例所示,需要分析#22业务执行耗时逻辑是否合理。
|
|
51
|
+
2. 任务执行超时分析步骤同[应用冻屏(AppFreeze)定位步骤与思路](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-stability-app-freeze-way#section1950514261110)。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 相机
|
|
2
|
+
|
|
3
|
+
> 来源: https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-photo
|
|
4
|
+
> 文档标识(fileName): bpta-photo
|
|
5
|
+
> 目录(catalogName): best-practices
|
|
6
|
+
> 语言: cn
|
|
7
|
+
> 更新时间: 2026-06-23 03:35:19
|
|
8
|
+
> 导航地址: /hmos/hmos-dp1
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
- **[相机分段式拍照性能优化](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-camera-shot2see)**
|
|
12
|
+
- **[相机预览花屏解决方案](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-deal-stride-solution)**
|
|
13
|
+
- **[自定义相机预览](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-custom-camera-preview)**
|
|
14
|
+
- **[自定义相机拍照](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-custom-camera-photo)**
|
|
15
|
+
- **[自定义相机录像](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-custom-camera-video)**
|
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
# 图片预览器
|
|
2
|
+
|
|
3
|
+
> 来源: https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-picture-preview
|
|
4
|
+
> 文档标识(fileName): bpta-picture-preview
|
|
5
|
+
> 目录(catalogName): best-practices
|
|
6
|
+
> 语言: cn
|
|
7
|
+
> 更新时间: 2026-06-23 03:33:47
|
|
8
|
+
> 导航地址: /hmos/hmos-dp1
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
#### 概述
|
|
12
|
+
|
|
13
|
+
图片预览器是常见的开发应用场景。在诸多日常使用的软件中,图片预览器都是提升用户体验的关键组件。它允许用户在上传、分享或编辑图片之前,先对图片进行预览,从而确保图片的质量和效果符合预期。本文章将深入探讨实现图片预览器过程中的几个复杂场景,具体包括:图片如何“跟手”,如何计算并合理限制图片的边界,以及如何解决Swiper组件与滑动手势之间产生的冲突问题。
|
|
14
|
+
|
|
15
|
+

|
|
16
|
+
|
|
17
|
+
#### 实现原理
|
|
18
|
+
|
|
19
|
+
## 场景描述
|
|
20
|
+
|
|
21
|
+
基础的图片预览器功能包括如下操作:
|
|
22
|
+
|
|
23
|
+
1. 双指捏合图片,即实现对图片以双指中心点为基准点的缩放操作。
|
|
24
|
+
2. 双击图片即可切换其大小,当图片处于放大状态时,再次双击即恢复至默认尺寸。
|
|
25
|
+
3. 大图片支持左右滑动查看。
|
|
26
|
+
4. 点击或滑动图片指示器,主图会随之更新。
|
|
27
|
+
|
|
28
|
+
其中,缩放图片是通过矩阵变换功能matrix4来实现的,图片的平移是通过属性translate来实现的。
|
|
29
|
+
|
|
30
|
+
## 关键技术
|
|
31
|
+
|
|
32
|
+
图片预览器中的图片查看功能,主要由大图界面来承担,交互操作相对复杂。下面,简要梳理一下大图界面中基本手势的处理与计算方式。
|
|
33
|
+
|
|
34
|
+
**“跟手”的原理**
|
|
35
|
+
|
|
36
|
+
“跟手”操作细分为两大类别:平移“跟手”与缩放“跟手”。
|
|
37
|
+
|
|
38
|
+
在平移“跟手”中,无论用户的手指如何在屏幕上滑动,其触摸点相对于图片所保持的百分比位置始终保持不变。缩放“跟手”,则是在图片依据用户手势进行缩放调整时,用户手势的中心点不仅相对于屏幕上的坐标保持不变,而且相对于图片内容的百分比位置也保持不变。如下图所示,屏幕是蓝色区域,初始图片是橙色区域,放大后的图片是灰色区域。
|
|
39
|
+
|
|
40
|
+

|
|
41
|
+
|
|
42
|
+
假定当前图片位置是<lastScale, offsetX, offsetY>,控件原始宽高为<w, h>,本次缩放图片的缩放值为scale,缩放的中心点百分比位置为<centerX, centerY>,偏移为<offX, offY>,计算终点位置设为<scale', offsetX', offsetY'>。
|
|
43
|
+
|
|
44
|
+

|
|
45
|
+
|
|
46
|
+
如上图所示,假定缩放时,未发生偏移,蓝色看作交互开始时的控件,橙色是交互后的控件,如果缩放中心点在图片中心(图1),那么控件最终的offset没有任何变化;如果缩放中心在最左边缘(图3),在放大的过程中,整个控件的中心向右发生了偏移。由此,可以计算出图片的最终位置。其中,图2、图3中的问号代表图片的偏移量,而图中的橙色圆点是图片缩放操作的中心点。在以下计算公式中,0.5 表示图片中心点的百分比位置,即 50% = 0.5。
|
|
47
|
+
|
|
48
|
+
- scale' = 上次手势结束时的缩放值 * 本次缩放图片的缩放值。
|
|
49
|
+
|
|
50
|
+
= lastScale * scale
|
|
51
|
+
- offsetX' = 平移带来的偏移 + 缩放中心不在中心而带来的偏移。
|
|
52
|
+
|
|
53
|
+
= (offsetX + offX) + (0.5 - centerX) * 控件大小变化之差
|
|
54
|
+
|
|
55
|
+
= (offsetX + offX) + (0.5 - centerX) * (w * lastScale - w * lastScale * scale)
|
|
56
|
+
|
|
57
|
+
= (offsetX + offX) + (0.5 - centerX) * w * (scale - 1) * lastScale
|
|
58
|
+
|
|
59
|
+
= (offsetX + offX) + (0.5 - centerX) * w * (1 - scale) * lastScale
|
|
60
|
+
- 同理 offsetY' = 平移带来的偏移 + 缩放中心不在中心而带来的偏移。
|
|
61
|
+
|
|
62
|
+
= (offsetY + offY) + (0.5 - centerY) * h * (1 - scale) * lastScale
|
|
63
|
+
|
|
64
|
+
缩放中心百分比位置<centerX , centerY>计算。如下图,橙色为手机屏幕,触摸点反馈的坐标(x,y)是相较屏幕左上角的(假设控件布满全屏)。
|
|
65
|
+
|
|
66
|
+

|
|
67
|
+
- centerX = ( x - imgX ) / imgWidth
|
|
68
|
+
|
|
69
|
+
= ( 触摸点坐标x- X方向图片左上角的坐标)/ 图片的宽度
|
|
70
|
+
|
|
71
|
+
= ( 触摸点坐标x- ( ( 组件屏幕的宽度 - 当前图片的宽度) / 2 +上次图片X方向的偏移量)) / 图片的宽度
|
|
72
|
+
- 同理 centerY = ( y - imgY ) / imgHeight
|
|
73
|
+
|
|
74
|
+
= ( 触摸点坐标y- Y方向图片左上角的坐标 ) / 图片的高度
|
|
75
|
+
|
|
76
|
+
= ( 触摸点坐标y- ( ( 组件屏幕的高度 - 当前图片的高度) / 2 +上次图片Y方向的偏移量)) / 图片的高度
|
|
77
|
+
|
|
78
|
+
**边界限制的原理**
|
|
79
|
+
|
|
80
|
+
边界计算涉及两个方面:当前图片显示边界计算、offset范围计算。
|
|
81
|
+
|
|
82
|
+
- 当前图片显示边界计算可得出当前图片显示的位置,左右上下是否与显示区域边界对齐,如果已经对齐,则不能继续往某个方向继续拖动。
|
|
83
|
+
- 平移/缩放时必须对offset作限制,否则图片将被移出显示区域或是手势结束后周围有黑边。从原理上看,某个scale下offset(x&y方向上)的范围是固定的,所以只需在手势交互时根据当前的scale计算得出offsetRange即可(超出边界时取边界作为结果)。
|
|
84
|
+
|
|
85
|
+
假定下面两个图中显示区域为黑框区域,当前放大倍率是curScale。
|
|
86
|
+
|
|
87
|
+
如下图,当X方向offset到达上界时图片上边缘x坐标等于0:
|
|
88
|
+
|
|
89
|
+

|
|
90
|
+
|
|
91
|
+
到达下界时,图片右边缘与显示区域右边缘重合:
|
|
92
|
+
|
|
93
|
+

|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
// Calculate the actual display size of the scaled image.
|
|
97
|
+
let scaledImageWidth = this.imageWidth * this.curScale;
|
|
98
|
+
let scaledImageHeight = this.imageHeight * this.curScale;
|
|
99
|
+
|
|
100
|
+
// Calculation of X-axis boundaries
|
|
101
|
+
if (scaledImageWidth > this.componentWidth) {
|
|
102
|
+
// If the width of the picture exceeds the width of the screen, you can move it left and right.
|
|
103
|
+
let maxXOffset = (scaledImageWidth - this.componentWidth) / 2;
|
|
104
|
+
this.maxOffsetX = maxXOffset;
|
|
105
|
+
this.minOffsetX = -maxXOffset;
|
|
106
|
+
} else {
|
|
107
|
+
// The width of the image does not exceed the width of the screen. It should be centered and no X-axis offset is allowed.
|
|
108
|
+
this.maxOffsetX = 0;
|
|
109
|
+
this.minOffsetX = 0;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Y方向同理,上下界为:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
// Calculate the actual display size of the scaled image.
|
|
117
|
+
let scaledImageWidth = this.imageWidth * this.curScale;
|
|
118
|
+
let scaledImageHeight = this.imageHeight * this.curScale;
|
|
119
|
+
|
|
120
|
+
// ...
|
|
121
|
+
|
|
122
|
+
// Y-axis boundary calculation
|
|
123
|
+
if (scaledImageHeight > this.componentHeight) {
|
|
124
|
+
// If the image height exceeds the screen height, it can be scrolled up and down.
|
|
125
|
+
let maxYOffset = (scaledImageHeight - this.componentHeight) / 2;
|
|
126
|
+
this.maxOffsetY = maxYOffset;
|
|
127
|
+
this.minOffsetY = -maxYOffset;
|
|
128
|
+
} else {
|
|
129
|
+
// The height of the image does not exceed the height of the screen. It should be centered and no Y-axis offset is allowed.
|
|
130
|
+
this.maxOffsetY = 0;
|
|
131
|
+
this.minOffsetY = 0;
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### 场景实现
|
|
136
|
+
|
|
137
|
+
## 跟手的实现
|
|
138
|
+
|
|
139
|
+
跟手技术细分为两大类别:平移“跟手”与缩放“跟手”,接下来,将对这两者进行讲解。
|
|
140
|
+
|
|
141
|
+

|
|
142
|
+
|
|
143
|
+
1. 响应平移手势:使用PanGesture接口实现滑动手势控制,为了实现单指滑动效果,需将参数fingers设置为1,当图片拖动后,即可获取当前图片的偏移量,具体为event.offsetX与event.offsetY。
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
// Slide picture
|
|
147
|
+
// Swiping left and right under the default size should switch images
|
|
148
|
+
PanGesture({ fingers: 1, distance: this.isDisableSwipe ? 3 : 50 })
|
|
149
|
+
.onActionUpdate((event: GestureEvent) => {
|
|
150
|
+
this.isDisableSwipe = this.imageModel.panGestureUpdate(event);
|
|
151
|
+
})
|
|
152
|
+
.onActionEnd(() => {
|
|
153
|
+
this.imageModel.gestureEnd();
|
|
154
|
+
}),
|
|
155
|
+
```
|
|
156
|
+
2. 图片平移:在onScale()方法中,算出图片经过拖动后,在X轴方向和Y轴方向上的新位置,分别为curOffsetX和curOffsetY,即为平移“跟手”后图片的位置。
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
// Pan gestures callback during movement.
|
|
160
|
+
panGestureUpdate(event: GestureEvent): boolean {
|
|
161
|
+
this.onScale(event.scale, event.offsetX, event.offsetY);
|
|
162
|
+
this.pictureBoundaryRestriction();
|
|
163
|
+
return this.isDisableSwipe;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ...
|
|
167
|
+
|
|
168
|
+
// Calculates the offset X and offset Y of the current picture and the scaling value of the current picture.
|
|
169
|
+
onScale(scale: number, offX: number, offY: number): void {
|
|
170
|
+
// ...
|
|
171
|
+
if (this.curScale < this.maxScale) {
|
|
172
|
+
this.curOffsetY =
|
|
173
|
+
(this.lastOffsetY + offY) + (0.5 - this.centerY) * this.imageHeight * (1 - scale) * this.lastScale;
|
|
174
|
+
this.curOffsetX =
|
|
175
|
+
(this.lastOffsetX + offX) + (0.5 - this.centerX) * this.imageWidth * (1 - scale) * this.lastScale;
|
|
176
|
+
}
|
|
177
|
+
// When the image is in the process of moving, it has not reached the boundary point.
|
|
178
|
+
this.isArriveBoundary = false;
|
|
179
|
+
// If the image has not reached the boundary, do not allow the image to be switched.
|
|
180
|
+
if (!this.isArriveBoundary) {
|
|
181
|
+
this.isDisableSwipe = true;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
3. 响应缩放手势:使用捏合手势PinchGesture接口,将参数fingers设置为2。当捏合手势识别成功时,onActionStart()回调被适时触发,在这一过程中,会计算出当前图片缩放中心百分比位置。手势移动过程中会触发onActionUpdate()回调函数,在onActionUpdate()回调函数里计算出当前图片的缩放值以及图片在X方向和Y方向的偏移量,并实时更新图片的位置。
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
// Two-finger scaling
|
|
189
|
+
PinchGesture({ fingers: 2, distance: 1 })
|
|
190
|
+
.onActionStart((event: GestureEvent) => {
|
|
191
|
+
this.imageModel.pinchGestureStart(event);
|
|
192
|
+
if (this.isOverlay) {
|
|
193
|
+
this.isOverlay = false;
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
.onActionUpdate((event: GestureEvent) => {
|
|
197
|
+
this.isDisableSwipe = this.imageModel.pinchGestureUpdate(event);
|
|
198
|
+
})
|
|
199
|
+
.onActionEnd(() => {
|
|
200
|
+
this.imageModel.pinchGestureEnd();
|
|
201
|
+
}),
|
|
202
|
+
```
|
|
203
|
+
4. 图片缩放中心百分比位置的计算:成功识别到双指捏合手势触发onActionStart()函数,计算出图片缩放中心的百分比位置this.center,this.center用于图片缩放时,所产生的偏移量(若缩放中心并非位于图片中心点),下面将具体介绍图片缩放中心的百分比位置的计算方法:
|
|
204
|
+
- cX = Math.max((centerX - imgX) / imgDisplayWidth, 0)
|
|
205
|
+
|
|
206
|
+
= Math.max((centerX - ((this.componentWidth - ( (this.imageWidth * this.lastScale))) / 2 + this.lastOffsetX)) / (this.imageWidth * this.lastScale), 0)
|
|
207
|
+
|
|
208
|
+
= Math.max((捏合手势中心点的X轴坐标 - ((组件屏幕的宽度 - (图片的宽度 * 上次图片的缩放值)) / 2 + 上次图片X方向的偏移量)) / ( 图片的宽度 * 上次图片的缩放值 ), 0)
|
|
209
|
+
- cY = Math.max((centerY - imgY) / imgDisplayHeight, 0);
|
|
210
|
+
|
|
211
|
+
= Math.max((centerY - ((this.componentHeight - (this.imageHeight * this.lastScale)) / 2 + this.lastOffsetY)) / (this.imageHeight * this.lastScale), 0)
|
|
212
|
+
|
|
213
|
+
= Math.max((捏合手势中心点的Y轴坐标 - ((组件屏幕的高度 - (图片的高度 * 上次图片的缩放值)) / 2 + 上次图片Y方向的偏移量)) / (图片的高度 * 上次图片的缩放值), 0)
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
// Calculates the percentage position of the current zoom center relative to the picture
|
|
217
|
+
evaluateCenter(centerX: number, centerY: number): [number, number] {
|
|
218
|
+
let imgDisplayWidth = this.imageWidth * this.lastScale;
|
|
219
|
+
let imgDisplayHeight = this.imageHeight * this.lastScale;
|
|
220
|
+
let imgX = (this.componentWidth - imgDisplayWidth) / 2 + this.lastOffsetX;
|
|
221
|
+
let imgY = (this.componentHeight - imgDisplayHeight) / 2 + this.lastOffsetY;
|
|
222
|
+
let cX = Math.max((centerX - imgX) / imgDisplayWidth, 0);
|
|
223
|
+
let cY = Math.max((centerY - imgY) / imgDisplayHeight, 0);
|
|
224
|
+
return [cX, cY];
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// ...
|
|
228
|
+
|
|
229
|
+
// Pinch gesture recognition successful callback.
|
|
230
|
+
pinchGestureStart(event: GestureEvent): void {
|
|
231
|
+
this.center = this.evaluateCenter(event.pinchCenterX, event.pinchCenterY);
|
|
232
|
+
this.centerX = 1 - this.center[0];
|
|
233
|
+
this.centerY = 1 - this.center[1];
|
|
234
|
+
AppStorage.setOrCreate('isImgDefaultSize', false);
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
5. 图片缩放:在捏合手势触发移动操作时,通过调用自定义onScale()方法,计算得出当前图片的缩放值以及由双指缩放动作引起的水平偏移量curOffsetX和垂直偏移量curOffsetY,最后,调用matrix4.identity().scale()对图片进行缩放,至此,图片的缩放“跟手”操作已完成。
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
// General picture scaling value method.
|
|
241
|
+
pictureScaling(scale: number): void {
|
|
242
|
+
this.matrix = matrix4.identity().scale({
|
|
243
|
+
x: scale,
|
|
244
|
+
y: scale
|
|
245
|
+
}).copy();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// ...
|
|
249
|
+
|
|
250
|
+
// Pinch gestures callback during a move.
|
|
251
|
+
pinchGestureUpdate(event: GestureEvent): boolean {
|
|
252
|
+
this.onScale(event.scale, event.offsetX, event.offsetY);
|
|
253
|
+
this.pictureScaling(this.curScale);
|
|
254
|
+
if (this.curScale > this.defaultScaleValue) {
|
|
255
|
+
this.isDisableSwipe = true;
|
|
256
|
+
}
|
|
257
|
+
this.pictureBoundaryRestriction();
|
|
258
|
+
return this.isDisableSwipe;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ...
|
|
262
|
+
|
|
263
|
+
// Calculates the offset X and offset Y of the current picture and the scaling value of the current picture.
|
|
264
|
+
onScale(scale: number, offX: number, offY: number): void {
|
|
265
|
+
if (this.lastScale * scale > this.maxScale) {
|
|
266
|
+
this.curScale = this.maxScale;
|
|
267
|
+
} else if (this.lastScale * scale < this.minScale) {
|
|
268
|
+
this.curScale = this.minScale;
|
|
269
|
+
} else {
|
|
270
|
+
this.curScale = this.lastScale * scale;
|
|
271
|
+
}
|
|
272
|
+
if (this.lastScale * scale === this.maxScale) {
|
|
273
|
+
this.curScale -= 0.001;
|
|
274
|
+
}
|
|
275
|
+
this.evaluateOffsetRange();
|
|
276
|
+
if (this.curScale < this.maxScale) {
|
|
277
|
+
this.curOffsetY =
|
|
278
|
+
(this.lastOffsetY + offY) + (0.5 - this.centerY) * this.imageHeight * (1 - scale) * this.lastScale;
|
|
279
|
+
this.curOffsetX =
|
|
280
|
+
(this.lastOffsetX + offX) + (0.5 - this.centerX) * this.imageWidth * (1 - scale) * this.lastScale;
|
|
281
|
+
}
|
|
282
|
+
// When the image is in the process of moving, it has not reached the boundary point.
|
|
283
|
+
this.isArriveBoundary = false;
|
|
284
|
+
// If the image has not reached the boundary, do not allow the image to be switched.
|
|
285
|
+
if (!this.isArriveBoundary) {
|
|
286
|
+
this.isDisableSwipe = true;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## 边界限制的实现
|
|
292
|
+
|
|
293
|
+
1. 图片边界限制:主要涉及两个方面:当前图片显示边界的计算以及offset范围计算。
|
|
294
|
+
|
|
295
|
+
调用自定义initCurrentImageInfo()方法,计算出当前图片的宽度this.imageModel.imageWidth和高度this.imageModel.imageHeight。
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
/**
|
|
299
|
+
* Set information about the current image: uri, whRatio, pixelMap, defaultSize, maxScaleValue
|
|
300
|
+
* Obtain the Image information in advance for the size setting of
|
|
301
|
+
* the image component and subsequent related calculations
|
|
302
|
+
*/
|
|
303
|
+
initCurrentImageInfo(): void {
|
|
304
|
+
try {
|
|
305
|
+
let img = this.context.resourceManager.getMediaContentSync(this.imageData?.id);
|
|
306
|
+
let imageSource = image.createImageSource(img.buffer.slice(0));
|
|
307
|
+
imageSource.getImageInfo(0).then((data: image.ImageInfo) => {
|
|
308
|
+
this.imageWHRatio = data.size.width / data.size.height;
|
|
309
|
+
// Calculate scale ratios for both width and height to ensure image fits completely
|
|
310
|
+
let widthRatio = this.imageModel.componentWidth / data.size.width;
|
|
311
|
+
let heightRatio = this.imageModel.componentHeight / data.size.height;
|
|
312
|
+
// Use the smaller ratio to ensure the image fits within the screen bounds
|
|
313
|
+
let scaleRatio = Math.min(widthRatio, heightRatio);
|
|
314
|
+
this.imageModel.imageWidth = data.size.width * scaleRatio;
|
|
315
|
+
this.imageModel.imageHeight = data.size.height * scaleRatio;
|
|
316
|
+
}).catch((err: BusinessError) => {
|
|
317
|
+
hilog.error(0x0000, TAG, `[error][getImageInfo]${err.message}`);
|
|
318
|
+
});
|
|
319
|
+
} catch (err) {
|
|
320
|
+
hilog.error(0x0000, TAG, `GetMediaContentSync failed. Cause code: ${err.code}, message: ${err.message}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
调用自定义windowSize()方法,计算出当前组件的宽度this.componentWidth和高度this.componentHeight。
|
|
326
|
+
|
|
327
|
+
最后,调用自定义evaluateOffsetRange()方法,在图片缩放后,计算出图片在四个方向上的边界值:具体包括最大水平偏移量this.maxOffsetX、最小水平偏移量this.minOffsetX、最大垂直偏移量this.maxOffsetY以及最小垂直偏移量this.minOffsetY
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
// Get window size.
|
|
331
|
+
windowSize(): void {
|
|
332
|
+
window.getLastWindow(context).then((window: window.Window) => {
|
|
333
|
+
try {
|
|
334
|
+
this.componentWidth = uiContext!.px2vp(window.getWindowProperties().windowRect.width);
|
|
335
|
+
this.componentHeight = uiContext!.px2vp(window.getWindowProperties().windowRect.height);
|
|
336
|
+
} catch (err) {
|
|
337
|
+
hilog.error(DOMAIN, TAG, FORMAT,
|
|
338
|
+
`GetWindowProperties failed. Cause code: ${err.code}, message: ${err.message}`);
|
|
339
|
+
}
|
|
340
|
+
}).catch((err: BusinessError) => {
|
|
341
|
+
hilog.error(DOMAIN, TAG, FORMAT, `GetLastWindow failed. Cause code: ${err.code}, message: ${err.message}`);
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// ...
|
|
346
|
+
|
|
347
|
+
// Calculate the range of the picture boundary.
|
|
348
|
+
evaluateOffsetRange(): void {
|
|
349
|
+
// Calculate the actual display size of the scaled image.
|
|
350
|
+
let scaledImageWidth = this.imageWidth * this.curScale;
|
|
351
|
+
let scaledImageHeight = this.imageHeight * this.curScale;
|
|
352
|
+
|
|
353
|
+
// Calculation of X-axis boundaries
|
|
354
|
+
if (scaledImageWidth > this.componentWidth) {
|
|
355
|
+
// If the width of the picture exceeds the width of the screen, you can move it left and right.
|
|
356
|
+
let maxXOffset = (scaledImageWidth - this.componentWidth) / 2;
|
|
357
|
+
this.maxOffsetX = maxXOffset;
|
|
358
|
+
this.minOffsetX = -maxXOffset;
|
|
359
|
+
} else {
|
|
360
|
+
// The width of the image does not exceed the width of the screen. It should be centered and no X-axis offset is allowed.
|
|
361
|
+
this.maxOffsetX = 0;
|
|
362
|
+
this.minOffsetX = 0;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Y-axis boundary calculation
|
|
366
|
+
if (scaledImageHeight > this.componentHeight) {
|
|
367
|
+
// If the image height exceeds the screen height, it can be scrolled up and down.
|
|
368
|
+
let maxYOffset = (scaledImageHeight - this.componentHeight) / 2;
|
|
369
|
+
this.maxOffsetY = maxYOffset;
|
|
370
|
+
this.minOffsetY = -maxYOffset;
|
|
371
|
+
} else {
|
|
372
|
+
// The height of the image does not exceed the height of the screen. It should be centered and no Y-axis offset is allowed.
|
|
373
|
+
this.maxOffsetY = 0;
|
|
374
|
+
this.minOffsetY = 0;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
2. 图片在滑动或缩放过程中,一旦触及边界,便会触发restrictBound()方法进行判断。若图片抵达最上方边界,则立即将当前Y方向的偏移位置this.curOffsetY设置为该方向的最大偏移值this.maxOffsetY,以此实现对边界的有效限制。同样的逻辑也适用于其他三个方向:当图片到达最下方、最左侧或最右侧边界时,也会相应地调整其偏移位置,确保图片始终在规定的范围内活动。
|
|
379
|
+
|
|
380
|
+
当图片滑动至左边界或右边界时,this.isDisableSwipe会被设置为false;此时,Swiper组件将激活滑动切换功能,允许用户切换图片。
|
|
381
|
+
|
|
382
|
+

|
|
383
|
+
|
|
384
|
+
```
|
|
385
|
+
// Picture Boundary Restriction
|
|
386
|
+
pictureBoundaryRestriction(): void {
|
|
387
|
+
// X-axis boundary restriction
|
|
388
|
+
if (this.curOffsetX > this.maxOffsetX) {
|
|
389
|
+
this.curOffsetX = this.maxOffsetX;
|
|
390
|
+
this.isDisableSwipe = false;
|
|
391
|
+
this.isArriveBoundary = true;
|
|
392
|
+
} else if (this.curOffsetX < this.minOffsetX) {
|
|
393
|
+
this.curOffsetX = this.minOffsetX;
|
|
394
|
+
this.isDisableSwipe = false;
|
|
395
|
+
this.isArriveBoundary = true;
|
|
396
|
+
}
|
|
397
|
+
// Y-axis boundary limit
|
|
398
|
+
if (this.curOffsetY > this.maxOffsetY) {
|
|
399
|
+
this.curOffsetY = this.maxOffsetY;
|
|
400
|
+
} else if (this.curOffsetY < this.minOffsetY) {
|
|
401
|
+
this.curOffsetY = this.minOffsetY;
|
|
402
|
+
}
|
|
403
|
+
// When the image cannot fill the entire screen, force it to be centered.
|
|
404
|
+
let scaledImageWidth = this.imageWidth * this.curScale;
|
|
405
|
+
let scaledImageHeight = this.imageHeight * this.curScale;
|
|
406
|
+
if (scaledImageWidth <= this.componentWidth) {
|
|
407
|
+
// The width of the image does not exceed the screen. Force the X-axis to be centered.
|
|
408
|
+
this.curOffsetX = 0;
|
|
409
|
+
}
|
|
410
|
+
if (scaledImageHeight <= this.componentHeight) {
|
|
411
|
+
// The height of the image does not exceed the screen, and the Y-axis is forced to be centered.
|
|
412
|
+
this.curOffsetY = 0;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## 实现Swiper组件与滑动手势冲突的解决方案
|
|
418
|
+
|
|
419
|
+
当Swiper组件与PanGesture滑动手势事件在同一组件上并发作用时,两者之间的冲突会导致Swiper无法正常切换图片。下面,将详细讲解如何有效解决Swiper组件与滑动手势之间的冲突问题。
|
|
420
|
+
|
|
421
|
+

|
|
422
|
+
|
|
423
|
+
- Swiper组件内包含了[PanGesture](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-gestures-pangesture)拖动手势事件,用于滑动轮播子组件。[disableSwipe](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-swiper#disableswipe8)属性设为true会取消内部的PanGesture事件监听。
|
|
424
|
+
|
|
425
|
+
1. 需要将Swiper组件的disableSwipe属性设置为变量this.isDisableSwipe,即disableSwipe(this.isDisableSwipe)。
|
|
426
|
+
|
|
427
|
+
当图片处于默认尺寸,或是已滑动到左右边界之时,应将this.isDisableSwipe的值设定为false;当图片处于放大状态且尚未滑动至左右边界时,应将this.isDisableSwipe的值设定为true。
|
|
428
|
+
|
|
429
|
+
```
|
|
430
|
+
@Builder
|
|
431
|
+
PhotoSwiper() {
|
|
432
|
+
Swiper(this.homeSwipeController) {
|
|
433
|
+
ForEach(this.ImgData, (img: Resource) => {
|
|
434
|
+
ImageItemView({
|
|
435
|
+
imageData: img,
|
|
436
|
+
isOverlay: this.isOverlay
|
|
437
|
+
})
|
|
438
|
+
.width('100%')
|
|
439
|
+
.height('100%')
|
|
440
|
+
}, (img: Resource, index: number) => JSON.stringify(img) + index)
|
|
441
|
+
}
|
|
442
|
+
// ...
|
|
443
|
+
.disableSwipe(this.isDisableSwipe)
|
|
444
|
+
// ...
|
|
445
|
+
```
|
|
446
|
+
2. PanGesture接口被用于实现滑动手势控制,其中参数distance需根据变量进行动态设置与判断。具体而言,当this.isDisableSwipe被设置为true时,Swiper组件将禁用滑动切换功能,此时,为了保持拖动图片时的流畅性,需要将distance的值设定为一个较小的数值。相反,当this.isDisableSwipe为false时,Swiper组件则会启用滑动切换功能,此时,为了让用户能够更灵敏地触发Swiper组件的滑动操作,distance的值则需适当增大,以优化用户的交互体验。至此,Swiper组件与滑动手势之间的冲突问题便得到解决。
|
|
447
|
+
|
|
448
|
+
```
|
|
449
|
+
PanGesture({ fingers: 1, distance: this.isDisableSwipe ? 3 : 50 })
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
#### 常见问题
|
|
453
|
+
|
|
454
|
+
## 在Swiper组件中,当为图片子组件配置了PanGesture后,swiper无法正常翻页,该如何解决手势冲突?
|
|
455
|
+
|
|
456
|
+
通过使用Swiper组件的disableSwipe属性,进行动态赋值,在图片保持默认尺寸或图片在放大状态下已触及边界时,将disableSwipe属性设置为false,从而使得Swiper能够切换图片;当图片处于放大状态且尚未到达边界时,则将disableSwipe属性设为true,此时Swiper的切换功能将被禁用。
|
|
457
|
+
|
|
458
|
+
## 当图片被放大后,若在拖动图片的过程中,该如何控制其边界,确保图片不会超出显示区域的界限?
|
|
459
|
+
|
|
460
|
+
该问题涉及到图片边界的约束。主要涉及两个方面:当前图片显示边界计算以及offset范围计算。当前图片显示边界计算可得出当前图片显示的位置,左右上下是否与显示区域边界对齐,如果已经对齐,则不能继续往某个方向继续拖动。平移/缩放时必须对offset作限制,否则图片将被移出显示区域或是手势结束后周围有黑边。只需在手势交互时根据当前的scale计算得出offset的范围即可(超出边界时取边界作为结果),即可对图片边界进行限制。
|
|
461
|
+
|
|
462
|
+
#### 示例代码
|
|
463
|
+
|
|
464
|
+
- [基于ArkUI实现图片预览功能](https://gitcode.com/harmonyos_samples/PicturePreview)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# 图片
|
|
2
|
+
|
|
3
|
+
> 来源: https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-picture
|
|
4
|
+
> 文档标识(fileName): bpta-picture
|
|
5
|
+
> 目录(catalogName): best-practices
|
|
6
|
+
> 语言: cn
|
|
7
|
+
> 更新时间: 2026-06-23 03:35:19
|
|
8
|
+
> 导航地址: /hmos/hmos-dp1
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
- **[图片获取与保存实践](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-image_get_and_save)**
|
|
12
|
+
- **[长截图](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-long-snapshot-practice)**
|