HarmonyOS 图片旋转自适应屏幕宽高功能的实现?

图片旋转不能自适应屏幕宽高,请问有代码怎么实现或者有第三方库吗?

阅读 408
1 个回答

给image()设置.objectFit(ImageFit.Contain)属性,将图片转换成pixelMap后,对pixelMap格式的图片进行旋转,既可以达到图片旋转自适应宽高的效果。

参考如下demo:

// EntryAbility.ets
import { UIAbility, abilityAccessCtrl, Permissions, Want, AbilityConstant } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  }

  onDestroy() {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage) {
    // Main window is created, set main page for this ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
    const permissions: Array<Permissions> = [
      'ohos.permission.WRITE_IMAGEVIDEO',
      'ohos.permission.WRITE_MEDIA',
      'ohos.permission.READ_MEDIA',
      'ohos.permission.MEDIA_LOCATION'
    ];
    const atManager = abilityAccessCtrl.createAtManager();
    atManager.requestPermissionsFromUser(this.context, permissions, (err, data) => {
      if (err) {
        hilog.error(0x0000, 'testTag', 'Failed to requestPermission. Cause: %{public}s',
          JSON.stringify(err) ?? '');
      } else {
        hilog.info(0x0000, 'testTag', 'Succeeded in requestPermission. Data: %{public}s',
          JSON.stringify(data) ?? '');
      }
    });

    windowStage.getMainWindow((_err, windowClass) => {
      windowClass.setWindowLayoutFullScreen(false, (err) => {
        if (err.code) {
          hilog.error(0x0000, 'EntryAbility',
            'Failed to set the window layout to no-full-screen mode. Cause:' + JSON.stringify(err));
          return;
        }
        hilog.info(0x0000, 'EntryAbility', 'Succeeded in setting the window layout to no-full-screen mode.');
      });
    });

    windowStage.loadContent('pages/HomePage', (err, data) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s',
          JSON.stringify(err) ?? '');
        return;
      }
      let windowClass: window.Window = windowStage.getMainWindowSync(); // 获取应用主窗口
      // 1. 设置窗口全屏
      let isLayoutFullScreen = true;
      windowClass.setWindowLayoutFullScreen(isLayoutFullScreen)
        .then(() => {
          console.info('Succeeded in setting the window layout to full-screen mode.');
        })
        .catch((err: BusinessError) => {
          console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err));
        });

      // 2. 获取布局避让遮挡的区域
      let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR; // 以导航条避让为例
      let avoidArea = windowClass.getWindowAvoidArea(type);
      let bottomRectHeight = avoidArea.bottomRect.height; // 获取到导航条区域的高度
      AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);

      // 2. 设置状态栏和导航条隐藏
      windowClass.setSpecificSystemBarEnabled('status', false)
        .then(() => {
          console.info('Succeeded in setting the status bar to be invisible.');
        })
        .catch((err: BusinessError) => {
          console.error(`Failed to set the status bar to be invisible. Code is ${err.code}, message is ${err.message}`);
        });

      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
        JSON.stringify(data) ?? '');
    });
  }

  onWindowStageDestroy() {
    // Main window is destroyed, release UI related resources
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  onForeground() {
    // Ability has brought to foreground
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
  }

  onBackground() {
    // Ability has back to background
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
  }
}


// HomePage.ets
import { image } from '@kit.ImageKit';
import getPixelMap from '../utils/DecodeUtil';

const TAG: string = 'imageEdit';

enum RotateType {
  CLOCKWISE,
  ANTI_CLOCK
}

@Entry
@Component
struct HomePage {
  @State currentIndex: number = 0;
  @State currentCropIndex: number = 0;
  @Provide('pixelMap') pixelMap?: image.PixelMap = undefined;
  @Provide('imageInfo') imageInfo: image.ImageInfo = {
    size: { height: 0, width: 0 },
    density: 0,
    stride: 0,
    alphaType: 0,
    pixelFormat: 0,
    mimeType: '',
    isHdr: false
  };
  @Provide('currentAdjustData') currentAdjustData: Array<number> =
    [100, 100, 100].map((item: number) => item);
  @Provide('isPixelMapChange') @Watch('flushPixelMap') isPixelMapChange: boolean = false;

  rotateImage(rotateType: RotateType) {
    if (rotateType === RotateType.CLOCKWISE) {
      if (!this.pixelMap) {
        return;
      }
      try {
        this.pixelMap.rotate(90)
          .then(() => {
            this.flushPixelMapChange();
          })
      } catch (error) {
        console.error(TAG, `there is a error in rotate process with ${error?.code}`);
      }
    }
    if (rotateType === RotateType.ANTI_CLOCK) {
      if (!this.pixelMap) {
        return;
      }
      try {
        this.pixelMap.rotate(-90)
          .then(() => {
            this.flushPixelMapChange();
          })
      } catch (error) {
        console.error(TAG, `there is a error in rotate process with ${error?.code}`);
      }
    }
  }

  flushPixelMapChange() {
    this.isPixelMapChange = !this.isPixelMapChange;
  }

  flushPixelMap() {
    const temp = this.pixelMap;
    this.pixelMap = undefined;
    this.pixelMap = temp;
  }

  pixelInit() {
    getPixelMap(this)
      .then((pixelMap?: image.PixelMap) => {
        if (pixelMap) {
          this.isPixelMapChange = !this.isPixelMapChange;
          this.pixelMap = pixelMap;
        }
        this.currentCropIndex = 0;
        this.currentAdjustData = [100, 100, 100].map((item: number) => item);
      })
  }

  aboutToAppear() {
    this.pixelInit();
  }

  build() {
    Navigation() {
      Stack() {
        Column() {
          Blank().height("5%")
          Column() {
            if (this.isPixelMapChange) {
              Image(this.pixelMap)
                .objectFit(ImageFit.Contain)
            } else {
              Image(this.pixelMap)
                .objectFit(ImageFit.Contain)
            }
          }
          .width('100%')
          .height('70%')

          Column() {
            Row() {
              Image($r('app.media.ic_clockwise'))
                .width(36)
                .height(36)
                .margin({ right: '30%' })
                .onClick(() => {
                  this.rotateImage(RotateType.CLOCKWISE);
                })
              Image($r('app.media.ic_anti_clockwise'))
                .width(36)
                .height(36)
                .onClick(async () => {
                  this.rotateImage(RotateType.ANTI_CLOCK);
                })
            }
            .justifyContent(FlexAlign.Center)
            .width('100%')
            .height('100%')
          }
          .width('100%')
          .height('30%')
          .backgroundColor(Color.Black)
        }
        .width('100%')
        .height('100%')
        .backgroundColor(Color.Black)
      }
    }
    .titleMode(NavigationTitleMode.Mini)
    .backgroundColor(Color.Black)
    .hideBackButton(true)

  }
}


// DecodeUtil.ets
import { fileIo } from '@kit.CoreFileKit';
import { image } from '@kit.ImageKit';
import { CommonConstants } from '../common/constant/CommonConstants';

const TAG: string = 'imageEdit_Decode';

/**
 * Async get resource fd.
 *
 * @return file fd.
 */
async function getResourceFd(component: Object) {
  const context = getContext(component);
  const resourceMgr = context.resourceManager;
  let imageBuffer = await resourceMgr.getMediaContent($r("app.media.ic_low"))
  let filePath = context.cacheDir + '/' + CommonConstants.RAW_FILE_NAME;
  let file = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
  fileIo.writeSync(file.fd, imageBuffer.buffer);
  return file.fd;
}

/**
 * Async create pixel map.
 *
 * @return pixelMa.
 */
export default async function getPixelMap(component: Object) {
  const fd = await getResourceFd(component);
  const imageSourceApi = image.createImageSource(fd);
  if (!imageSourceApi) {
    console.error(TAG, 'imageSourceAPI created failed!');
    return;
  }
  const pixelMap = await imageSourceApi.createPixelMap({
    editable: true
  });
  return pixelMap;
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
logo
HarmonyOS
子站问答
访问
宣传栏