视频全屏时顶部有白条，随后消失
===============

#### 问题现象

视频切换到横屏全屏时，页面顶部短暂显示标题栏。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/82/v3/csYxyShDRhOYEBhAGTV3DA/zh-cn_image_0000002658840789.png?HW-CC-KV=V1&HW-CC-Date=20260709T134025Z&HW-CC-Expire=86400&HW-CC-Sign=8F3D916FF0B6C985AA7B5CEF111C8EE9922A90203F47E74D12D5BD9483F40060 "点击放大")

#### 背景知识

*   [XComponent](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-xcomponent)工作机制：HarmonyOS的XComponent是高性能渲染组件，通过Surface（详细参考[自定义渲染 (XComponent)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/napi-xcomponent-guidelines)）提供渲染缓冲区，支持[OpenGL](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/opengl)/[Vulkan](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/vulkan-guide)等图形API绘制动态内容（如预览流、3D模型）。
*   设置[onSurfaceChanged](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-xcomponent#onsurfacechanged12)时，当XComponent持有的Surface大小改变后（包括首次创建时的大小改变）进行该回调，仅XComponent类型为SURFACE("surface")或TEXTURE时有效。
*   使用[@ohos.mediaquery (媒体查询)](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-mediaquery)接口可监听屏幕旋转。

#### 问题定位

1.  使用DevEco Testing查看问题组件，问题组件为XComponent组件。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/8d/v3/XgR28b3jQcWqH3rLcy7K_A/zh-cn_image_0000002628761412.png?HW-CC-KV=V1&HW-CC-Date=20260709T134025Z&HW-CC-Expire=86400&HW-CC-Sign=7CF36CA11935A714C4532F1A5D8CE4978C48B4B9B9C25DC38B89440BB34BD5F0 "点击放大")
    
2.  排查该XComponent组件的相关设置，全屏时XComponent组件的尺寸重新变化后才触发去除视频上方的标题栏。
    
    class CustomXComponentController extends XComponentController {
      onSurfaceChanged(surfaceId: string, rect: SurfaceRect): void {
        console.info(\`onSurfaceChanged surfaceId: ${surfaceId}\`);
        if (rect.surfaceWidth > 2000) {
          AppStorage.setOrCreate('title', false); _// 转为横屏后不显示标题栏_
        } else {
          AppStorage.setOrCreate('title', true); _// 转为竖屏后显示标题栏_
        }
      }
    }
    
    @Entry
    @Component
    struct Index {
      private xComponentController: XComponentController = new CustomXComponentController();
      @StorageLink('title') showTitle: boolean = true; _// 控制标题栏显隐_
    
      @Builder
      CoverXComponent() {
        XComponent({
         _ // 装载视频容器_
          id: 'xComponent',
          type: XComponentType.SURFACE,
          controller: this.xComponentController
        })
      }
    
      build() {
        Column() {
          if (this.showTitle) {
            Stack() {
              Text('标题栏')
            }
          }
          Stack() {
            Stack() {
              this.CoverXComponent();
            }
          }
      }
    }
    

#### 分析结论

视频旋转后XComponent组件尺寸变化后才触发去除顶部标题栏，导致顶部标题栏消失延后。

#### 修改建议

使用mediaquery监听屏幕旋转，在屏幕旋转时就去除视频上方的标题栏。

aboutToAppear() {
  this.windowWidth = display.getDefaultDisplaySync().width;
  this.windowHeight = display.getDefaultDisplaySync().height;
  this.surfaceW = this.windowWidth \* SURFACE\_W;
  this.surfaceH = this.surfaceW / SURFACE\_H;
  this.isPaused = true;
  this.context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  window.getLastWindow(this.context).then((lastWindow) => {
    lastWindow.setWindowLayoutFullScreen(true);
  });
  let portraitFunc = (mediaQueryResult: mediaquery.MediaQueryResult): void => this.onPortrait(mediaQueryResult);
  this.listener.on('change', portraitFunc); _// 监听屏幕旋转_
}

_// 屏幕旋转时的回调函数_
onPortrait(mediaQueryResult: mediaquery.MediaQueryResult) {
 _ // 屏幕横屏_
  if (mediaQueryResult.matches) {
    _// 设置横屏时的surface尺寸_
    this.surfaceW = this.windowHeight \* SURFACE\_W;
    this.surfaceH = this.surfaceW / SURFACE\_H;
    AppStorage.setOrCreate('title', false); _// 转为横屏后不显示标题栏_
  }
 _ // 屏幕竖屏_
  else {
   _ // 设置竖屏时的surface尺寸_
    this.surfaceW = this.windowWidth \* SURFACE\_W;
    this.surfaceH = this.surfaceW / SURFACE\_H;
    AppStorage.setOrCreate('title', true); _// 转为竖屏后显示标题栏_
  }
  this.xComponentController.setXComponentSurfaceRect({ surfaceWidth: this.surfaceW, surfaceHeight: this.surfaceH });
}

完整示例：

import display from '@ohos.display';
import emitter from '@ohos.events.emitter';
import { common } from '@kit.AbilityKit';
import media from '@ohos.multimedia.media';
import { audio } from '@kit.AudioKit';
import { mediaquery, window } from '@kit.ArkUI';

const PROPORTION = 0.99; _// 占屏幕比例_
const SURFACE\_W = 0.9; _// 表面宽比例_
const SURFACE\_H = 1.78; _// 表面高比例_
const SET\_INTERVAL = 100; _// interval间隔时间_
const TIME\_ONE = 60000;
const TIME\_TWO = 1000;

let innerEventFalse: emitter.InnerEvent = {
  eventId: 1,
  priority: emitter.EventPriority.HIGH
};
let innerEventTrue: emitter.InnerEvent = {
  eventId: 2,
  priority: emitter.EventPriority.HIGH
};
let innerEventWH: emitter.InnerEvent = {
  eventId: 3,
  priority: emitter.EventPriority.HIGH
};

@Entry
@Component
struct XComponentTranslation {
  tag: string = 'AVPlayManager';
  private xComponentController: XComponentController = new XComponentController();
  private avPlayer: media.AVPlayer | null = null;
  private surfaceId: string = '';
  private intervalID: number = -1;
  private seekTime: number = -1;
  private context: common.UIAbilityContext | undefined = undefined;
  fileName: string = 'video3.mp4'; _// 'video.mp4'需要在src/main/resources/rawfile中替换为开发者需要的视频资源文件_
  isSwiping: boolean = false; _// 用户滑动过程中_
  @State isPaused: boolean = true; _// 暂停播放_
  @State xComponentFlag: boolean = false;
  @StorageLink('durationTime') durationTime: number = 0; _// 视频总时长_
  @StorageLink('currentTime') currentTime: number = 0; _// 视频当前时间_
  @State surfaceW: number | null = null;
  @State surfaceH: number | null = null;
  @State percent: number = 0;
  windowWidth: number = 300;
  windowHeight: number = 200;
  @State @Watch('changeOrientation') isFull: boolean = false;
  @StorageLink('title') showTitle: boolean = true;
  listener: mediaquery.MediaQueryListener =
    this.getUIContext().getMediaQuery().matchMediaSync('(orientation: landscape)'); _//监听横屏事件_

  getDurationTime(): number {
    return this.durationTime;
  }

  getCurrentTime(): number {
    return this.currentTime;
  }

  timeConvert(time: number): string {
    let min: number = Math.floor(time / TIME\_ONE);
    let second: string = ((time % TIME\_ONE) / TIME\_TWO).toFixed(0);
    second = second.padStart(2, '0');
    return \`${min}:${second}\`;
  }

  async msleepAsync(ms: number): Promise<boolean> {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(true);
      }, ms);
    });
  }

  async avSetupVideo() {
   _ // 通过UIAbilityContext的resourceManager成员的getRawFd接口获取媒体资源播放地址。_
    _// 返回类型为{fd,offset,length},fd为HAP包fd地址，offset为媒体资源偏移量，length为播放长度。_
    if (this.context === undefined) {
      return;
    }
    let fileDescriptor = await this.context.resourceManager.getRawFd(this.fileName);
    let avFileDescriptor: media.AVFileDescriptor =
      { fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length };

    if (this.avPlayer) {
      console.info(\`${this.tag}: init avPlayer release2createNew\`);
      this.avPlayer.release();
      await this.msleepAsync(1500);
    }
   _ // 创建avPlayer实例对象_
    this.avPlayer = await media.createAVPlayer();

   _ // 创建状态机变化回调函数_
    await this.setAVPlayerCallback((avPlayer: media.AVPlayer) => {
      this.percent = avPlayer.width / avPlayer.height;
      this.setVideoWH();
      this.durationTime = this.getDurationTime();
      setInterval(() => { _// 更新当前时间_
        if (!this.isSwiping) {
          this.currentTime = this.getCurrentTime();
        }
      }, SET\_INTERVAL);
    });

    _// 为fdSrc赋值触发initialized状态机上报_
    this.avPlayer.fdSrc = avFileDescriptor;

    this.avPlayer.on('audioInterrupt', (interruptEvent: audio.InterruptEvent) => {
      if (interruptEvent.forceType === audio.InterruptForceType.INTERRUPT\_FORCE) {
        _// 强制打断类型（INTERRUPT\_FORCE）：音频相关处理已由系统执行，应用需更新自身状态，做相应调整。_
        switch (interruptEvent.hintType) {
          case audio.InterruptHint.INTERRUPT\_HINT\_PAUSE:
            this.isPaused = true; _// 应用切换至音频暂停状态_
            let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
          _  // 调用该接口手动改变设备横竖屏状态_
            window.getLastWindow(context).then((lastWindow) => {
              lastWindow.setPreferredOrientation(window.Orientation.PORTRAIT);
            });
            break;
          case audio.InterruptHint.INTERRUPT\_HINT\_STOP:
          _  // 此分支表示系统已将音频流停止（永久失去焦点），为保持状态一致，应用需切换至音频暂停状态。_
            this.isPaused = true; _// 此句为简化处理，代表应用切换至音频暂停状态的若干操作。_
            break;
          default:
            break;
        }
      }
    });
  }

  avPlay(): void {
    if (this.avPlayer) {
      try {
        this.avPlayer.play();
      } catch (e) {
        console.error(\`${this.tag}: avPlay = ${JSON.stringify(e)}\`);
      }
    }
  }

  avPause(): void {
    if (this.avPlayer) {
      try {
        this.avPlayer.pause();
        console.info(\`${this.tag}: avPause==\`);
      } catch (e) {
        console.error(\`${this.tag}: avPause== ${JSON.stringify(e)}\`);
      }
    }
  }

  async avSeek(seekTime: number): Promise<void> {
    if (this.avPlayer) {
      try {
        console.info(\`${this.tag}: videoSeek  seekTime== ${seekTime}\`);
        this.avPlayer.seek(seekTime, 2);
        this.currentTime = seekTime;
      } catch (e) {
        console.error(\`${this.tag}: videoSeek== ${JSON.stringify(e)}\`);
      }
    }
  }

  _// 注册avplayer回调函数_
  async setAVPlayerCallback(callback: (avPlayer: media.AVPlayer) => void): Promise<void> {
  _  // seek操作结果回调函数_
    if (this.avPlayer == null) {
      console.error(\`${this.tag}: avPlayer has not init!\`);
      return;
    }
    this.avPlayer.on('seekDone', (seekDoneTime) => {
      console.info(\`${this.tag}: setAVPlayerCallback AVPlayer seek succeeded, seek time is ${seekDoneTime}\`);
    });
    this.avPlayer.on('speedDone', (speed) => {
      console.info(\`${this.tag}: setAVPlayerCallback AVPlayer speedDone, speed is ${speed}\`);
    });
  _  // error回调监听函数,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程_
    this.avPlayer.on('error', (err) => {
      console.error(\`${this.tag}: setAVPlayerCallback Invoke avPlayer failed ${JSON.stringify(err)}\`);
      if (this.avPlayer == null) {
        console.error(\`${this.tag}: avPlayer has not init on error\`);
        return;
      }
      this.avPlayer.reset();
    });
 _   // 状态机变化回调函数_
    this.avPlayer.on('stateChange', async (state) => {
      if (this.avPlayer == null) {
        console.info(\`${this.tag}: avPlayer has not init on state change\`);
        return;
      }
      switch (state) {
        case 'idle': _// 成功调用reset接口后触发该状态机上报_
          console.info(\`${this.tag}: setAVPlayerCallback AVPlayer state idle called.\`);
          break;
        case 'initialized': _// avplayer设置播放源后触发该状态上报_
          console.info(\`${this.tag}: setAVPlayerCallback AVPlayer state initialized called.\`);
          if (this.surfaceId) {
            this.avPlayer.surfaceId = this.surfaceId; _// 设置显示画面，当播放的资源为纯音频时无需设置_
            console.info(\`${this.tag}: setAVPlayerCallback this.avPlayer.surfaceId = ${this.avPlayer.surfaceId}\`);
            this.avPlayer.prepare();
          }
          break;
        case 'prepared': _// prepare调用成功后上报该状态机_
          console.info(\`${this.tag}: setAVPlayerCallback AVPlayer state prepared called.\`);
          this.avPlayer.on('bufferingUpdate', (infoType: media.BufferingInfoType, value: number) => {
            console.info(\`${this.tag}: bufferingUpdate called, infoType value: ${infoType}, value:${value}}\`);
          });
          this.durationTime = this.avPlayer.duration;
          this.currentTime = this.avPlayer.currentTime;
          this.avPlayer.play(); _// 调用播放接口开始播放_
          this.avPlayer.setSpeed(media.PlaybackSpeed.SPEED\_FORWARD\_1\_00\_X);
          callback(this.avPlayer);
          break;
        case 'playing': _// play成功调用后触发该状态机上报_
          console.info(\`${this.tag}: setAVPlayerCallback AVPlayer state playing called.\`);
          if (this.intervalID !== -1) {
            clearInterval(this.intervalID);
          }
          this.intervalID = setInterval(() => { _// 更新当前时间_
            AppStorage.setOrCreate('durationTime', this.durationTime);
            AppStorage.setOrCreate('currentTime', this.currentTime);
          }, 100);
        _  // 根据播放状态提交相应事件_
          let eventDataTrue: emitter.EventData = {
            data: {
              'flag': true
            }
          };
          let innerEventTrue: emitter.InnerEvent = {
            eventId: 2,
            priority: emitter.EventPriority.HIGH
          };
          emitter.emit(innerEventTrue, eventDataTrue);
          break;
        case 'completed': _// 播放结束后触发该状态机上报_
          console.info(\`${this.tag}: setAVPlayerCallback AVPlayer state completed called.\`);
          let eventDataFalse: emitter.EventData = {
            data: {
              'flag': false
            }
          };
          let innerEvent: emitter.InnerEvent = {
            eventId: 1,
            priority: emitter.EventPriority.HIGH
          };
          emitter.emit(innerEvent, eventDataFalse);
          if (this.intervalID !== -1) {
            clearInterval(this.intervalID);
          }
          this.avPlayer.off('bufferingUpdate');
          AppStorage.setOrCreate('currentTime', this.durationTime);
          break;
        case 'released':
          console.info(\`${this.tag}: setAVPlayerCallback released called.\`);
          break;
        case 'stopped':
          console.info(\`${this.tag}: setAVPlayerCallback AVPlayer state stopped called.\`);
          break;
        case 'error':
          console.error(\`${this.tag}: setAVPlayerCallback AVPlayer state error called.\`);
          break;
        case 'paused':
          console.info(\`${this.tag}: setAVPlayerCallback AVPlayer state paused called.\`);
          break;
        default:
          console.info(\`${this.tag}: setAVPlayerCallback AVPlayer state unknown called.\`);
          break;
      }
    });
   _ // 时间上报监听函数_
    this.avPlayer.on('timeUpdate', (time: number) => {
      this.currentTime = time;
    });
  }

  aboutToAppear() {
    this.windowWidth = display.getDefaultDisplaySync().width;
    this.windowHeight = display.getDefaultDisplaySync().height;
    this.surfaceW = this.windowWidth \* SURFACE\_W;
    this.surfaceH = this.surfaceW / SURFACE\_H;
    this.isPaused = true;
    this.context = this.getUIContext().getHostContext() as common.UIAbilityContext;
    window.getLastWindow(this.context).then((lastWindow) => {
      lastWindow.setWindowLayoutFullScreen(true);
    });
    let portraitFunc = (mediaQueryResult: mediaquery.MediaQueryResult): void => this.onPortrait(mediaQueryResult);
    this.listener.on('change', portraitFunc); _// 监听屏幕旋转_
  }

  _// 屏幕旋转时的回调函数_
  onPortrait(mediaQueryResult: mediaquery.MediaQueryResult) {
   _ // 屏幕横屏_
    if (mediaQueryResult.matches) {
    _  // 设置横屏时的surface尺寸_
      this.surfaceW = this.windowHeight \* SURFACE\_W;
      this.surfaceH = this.surfaceW / SURFACE\_H;
      AppStorage.setOrCreate('title', false); _// 转为横屏后不显示标题栏_
    }
   _ // 屏幕竖屏_
    else {
    _  // 设置竖屏时的surface尺寸_
      this.surfaceW = this.windowWidth \* SURFACE\_W;
      this.surfaceH = this.surfaceW / SURFACE\_H;
      AppStorage.setOrCreate('title', true); _// 转为竖屏后显示标题栏_
    }
    this.xComponentController.setXComponentSurfaceRect({ surfaceWidth: this.surfaceW, surfaceHeight: this.surfaceH });
  }


  changeOrientation() {
    let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
    window.getLastWindow(context).then((lastWindow) => {
      lastWindow.setPreferredOrientation(this.isFull ? window.Orientation.AUTO\_ROTATION\_LANDSCAPE :
        window.Orientation.PORTRAIT);
      lastWindow.setWindowSystemBarEnable(this.isFull ? \[\] : \['status', 'navigation'\]);
    });
  }

  aboutToDisappear() {
    if (this.avPlayer == null) {
      console.info(\`${this.tag}: avPlayer has not init aboutToDisappear\`);
      return;
    }
    this.avPlayer.release((err) => {
      if (err == null) {
        console.info(\`${this.tag}: videoRelease release success\`);
      } else {
        console.error(\`${this.tag}: videoRelease release failed, error message is = ${JSON.stringify(err.message)}\`);
      }
    });
    emitter.off(innerEventFalse.eventId);
  }

  onPageHide() {
    this.avPause();
    this.isPaused = false;
  }

  onPageShow() {
    emitter.on(innerEventTrue, (res: emitter.EventData) => {
      if (res.data) {
        this.isPaused = res.data.flag;
        this.xComponentFlag = res.data.flag;
      }
    });
    emitter.on(innerEventFalse, (res: emitter.EventData) => {
      if (res.data) {
        this.isPaused = res.data.flag;
      }
    });
    emitter.on(innerEventWH, (res: emitter.EventData) => {
      if (res.data) {
        this.windowWidth = res.data.width;
        this.windowHeight = res.data.height;
        this.setVideoWH();
      }
    });
    this.avPlay();
    this.isPaused = true;
   _ // 重新进入该页面时不退出沉浸式_
  }

  setVideoWH(): void {
    if (this.percent >= 1) { _// 横向视频_
      this.surfaceW = Math.round(this.windowWidth \* PROPORTION);
      this.surfaceH = Math.round(this.surfaceW / this.percent);
    } else { _// 纵向视频_
      this.surfaceH = Math.round(this.windowHeight \* PROPORTION);
      this.surfaceW = Math.round(this.surfaceH \* this.percent);
    }
  }

  @Builder
  CoverXComponent() {
    XComponent({
      _// 装载视频容器_
      id: 'xComponent',
      type: XComponentType.SURFACE,
      controller: this.xComponentController
    })
      .id('VideoView')
      .visibility(this.xComponentFlag ? Visibility.Visible : Visibility.Hidden)
      .onLoad(() => {
        this.surfaceId = this.xComponentController.getXComponentSurfaceId();
        this.xComponentController.setXComponentSurfaceRect({
          surfaceWidth: this.surfaceW,
          surfaceHeight: this.surfaceH
        });
        this.avSetupVideo();
      })
      .height('100%')
      .width('100%');
  }

  build() {
    Column() {
      if (this.showTitle) {
        Stack() {
          Text('标题栏')
            .textAlign(TextAlign.Center)
            .height(40)
            .width('100%');
        }
        .height('10%')
        .width('100%')
        .backgroundColor(Color.White)
        .alignContent(Alignment.Bottom);
      }
      Stack() {
        Stack() {
          this.CoverXComponent();
        }
        .alignContent(Alignment.Center)
        .id('VideoView')
        .height('100%')
        .width('100%');

        Column() {
          Blank();
          Column() {
            Row() {
              Row() {
               _ // 播放、暂停键_
               _ // $r('app.media.ic\_video\_play')和$r('app.media.ic\_video\_pause')需要更换为用户需要的图片资源_
                Image(this.isPaused ? $r('app.media.ic\_video\_play') : $r('app.media.ic\_video\_pause')) _// 暂停/播放_
                  .id(this.isPaused ? 'pause' : 'play')
                  .width(40)
                  .height(40)
                  .onClick(() => {
                    if (this.isPaused) {
                      this.avPause();
                      this.isPaused = false;
                    } else {
                      this.avPlay();
                      this.isPaused = true;
                    }
                  });
               _ // 左侧时间_
                Text(this.timeConvert(this.currentTime))
                  .id('currentTimeText')
                  .fontColor(Color.White)
                  .textAlign(TextAlign.End)
                  .fontWeight(FontWeight.Regular)
                  .margin({ left: 10 });
              };

             _ // 进度条_
              Row() {
                Slider({
                  value: this.currentTime,
                  min: 0,
                  max: this.durationTime,
                  style: SliderStyle.OutSet
                })
                  .id('Slider')
                  .blockColor(Color.White)
                  .trackColor(Color.Gray)
                  .selectedColor('#007DFF')
                  .showTips(false)
                  .onChange((value: number) => {
                    if (this.seekTime !== value) {
                      this.seekTime = value;
                      this.avSeek(Number.parseInt(value.toFixed(0)));
                    }
                  });
              }
              .layoutWeight(1);

              Row() {
               _ // 右侧时间_
                Text(this.timeConvert(this.durationTime))
                  .id('durationTimeText')
                  .fontColor(Color.White)
                  .fontWeight(FontWeight.Regular);
              };

             _ // $r('app.media.out')和$r('app.media.full')需要替换为开发者需要的图片资源文件_
              Image(this.isFull ? $r('app.media.out') : $r('app.media.full'))
                .width(30)
                .height(30)
                .objectFit(ImageFit.Contain)
                .onClick(() => {
                  this.isFull = !this.isFull; _// 点击全屏按钮横向全屏或退出全屏_
                })
                .margin({ left: 5 });
            }
            .justifyContent(FlexAlign.Center)
            .padding({ left: 10, right: 5 })
            .width('100%');
          }
          .width('100%')
          .justifyContent(FlexAlign.Center)
          .margin({ bottom: 10 });
        }
        .width('100%')
        .height('100%')
        .margin({ bottom: 20 });
      }
      .backgroundColor(Color.Black)
      .height(this.isFull ? '100%' : '90%')
      .width('100%');
    }
    .backgroundColor(Color.Black)
    .height('100%')
    .width('100%');
  }
}

效果图如下：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/64/v3/frcBmT97QZ6t7CMIYnz_Lw/zh-cn_image_0000002658960737.png?HW-CC-KV=V1&HW-CC-Date=20260709T134025Z&HW-CC-Expire=86400&HW-CC-Sign=50F94FEA9860C2EF253F592E502CDBD76DA8ED10AE22F5CFF08DFA8AE7ED8BB7 "点击放大")