[英]Different layouts in portrait and landscape mode
您可以通過代碼實現這一點首先,您必須制作動態約束的IBoutlet
常量約束: //這些約束在兩個方向上都保持相同
1- RedView頂級空間到Superview
2- RedView尾隨空間到Superview
3- BlueView超級視圖的領先空間
4- BlueView底部空間到SuperView
動態約束
肖像約束:
1- RedView高度
2- RedView垂直空間到BlueView
3- RedView領先空間到Superview
4- SuperView尾隨空間到Superview
LandScape約束:
1- RedView寬度
2- RedView水平空間到BlueView
3- RedView底部空間到Superview
4- BlueView頂級空間到Superview
現在您必須覆蓋在方向更改時調用的方法
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animateAlongsideTransition({ (UIViewControllerTransitionCoordinatorContext) -> Void in
let orient = UIApplication.sharedApplication().statusBarOrientation
switch orient {
case .Portrait:
print("Portrait")
self.ApplyportraitConstraint()
break
// Do something
default:
print("LandScape")
// Do something else
self.applyLandScapeConstraint()
break
}
}, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
print("rotation completed")
})
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
}
並稱這兩個功能
縱向定位功能
func ApplyportraitConstraint(){
self.view.addConstraint(self.RedViewHeight)
self.view.addConstraint(self.RedView_VerticalSpace_To_BlueView)
self.view.addConstraint(self.RedView_LeadingSpace_To_SuperView)
self.view.addConstraint(self.BlueView_TrailingSpace_To_SuperView)
self.view.removeConstraint(self.RedViewWidth)
self.view.removeConstraint(self.RedView_HorizontalSpace_To_BlueView)
self.view.removeConstraint(self.RedView_BottomSpace_To_SuperView)
self.view.removeConstraint(self.BlueView_TopSpace_To_SuperView)
}
LandScape定位功能
func applyLandScapeConstraint(){
self.view.removeConstraint(self.RedViewHeight)
self.view.removeConstraint(self.RedView_VerticalSpace_To_BlueView)
self.view.removeConstraint(self.RedView_LeadingSpace_To_SuperView)
self.view.removeConstraint(self.BlueView_TrailingSpace_To_SuperView)
self.view.addConstraint(self.RedViewWidth)
self.view.addConstraint(self.RedView_HorizontalSpace_To_BlueView)
self.view.addConstraint(self.RedView_BottomSpace_To_SuperView)
self.view.addConstraint(self.BlueView_TopSpace_To_SuperView)
}
希望通過編碼通過布局管理幫助理解它。 如果您仍然無法理解那么請檢查我的代碼
Github :
如果您有警告,只需將高度和寬度的約束優先級設置為999。
iPAD沒有橫向模式的大小等級。 我認為原因是在大多數情況下不需要它。 但是,當設備方向改變時,可以激活和停用約束,如接受的答案。
以下內容對iPhone用戶有所幫助。
是的,這可以在具有autolayout和size類的界面構建器中使用。 您不需要編碼。
首先你選擇尺寸類wAny hAny
以下是如何選擇尺寸等級。
在視圖控制器中添加兩個視圖。 在上面頂視圖和藍色視圖的紅色視圖。 就像你的第一張圖片一樣。
紅色視圖的約束是:
藍色視圖的約束是:
這都是為Potrait模式設置的。
現在您將大小類更改為wAny hCompact(第一行中的前兩列)。 這個類適用於iPhone風景。
現在您必須使用安裝和卸載概念。
紅色視圖會改變的約束:
這將使紅色視圖向右側以50寬度。
現在藍色視圖的約束更改:
添加兩個新約束:
這將附加藍色視圖左側的紅色視圖。
希望它對你有用。
注意 - 這里的答案很好,可以解決問題,但在舊版本的iOS上。
對於iOS11(Xcode 9),您應該考慮自適應布局,如下所示: https ://www.raywenderlich.com/162311/adaptive-layout-tutorial-ios-11-getting-started
是否可以使用自動布局? 或者使用少量代碼?
你需要兩個都為iPad做這些布局。
在視圖控制器中實現UIContentContainer協議 。
viewWillTransitionToSize(_ size: CGSize,withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
討論UIKit在更改呈現的視圖控制器視圖的大小之前調用此方法。 您可以在自己的對象中覆蓋此方法,並使用它來執行與大小更改相關的其他任務。 例如,容器視圖控制器可能使用此方法來覆蓋其嵌入的子視圖控制器的特征。 使用提供的協調器對象為您所做的任何更改設置動畫。
如果在自定義視圖控制器中覆蓋此方法,請始終在實現中的某個位置調用super,以便UIKit可以適當地轉發大小更改消息。 視圖控制器將大小更改消息轉發到其視圖和子視圖控制器。 演示控制器將尺寸更改轉發給其呈現的視圖控制器。
是您需要實施的方法。 在此方法中,您需要檢查大小的屬性寬度和高度,以確定布局應如何更改 - 即橫向或縱向布局。 注意,此方法告訴的,它會改變大小的通過。
我用Obj-C實現了這個並在我的github上發布該解決方案涉及一些代碼,大部分工作都集中在AutoLayout和命名約定...... README文件解釋了我是如何做到的。 我在ViewController上使用的代碼基本上就是這個方法:
- (void)setUpViewConstraintsForInterfaceOrientation:(InterfaceOrientation)interfaceOrientation {
self.lastOrientation = interfaceOrientation;
if (interfaceOrientation == Landscape) {
[NSLayoutConstraint deactivateConstraints:self.portraitConstraintsCollection];
[NSLayoutConstraint activateConstraints:self.landscapeConstraintsCollection];
} else if(interfaceOrientation == Portrait){
[NSLayoutConstraint deactivateConstraints:self.landscapeConstraintsCollection];
[NSLayoutConstraint activateConstraints:self.portraitConstraintsCollection];
}
[self.view layoutIfNeeded];
}
portraitConstraintsCollection和landscapeConstraintsCollection是IBOutletCollection屬性,用於管理方向的特定約束。
自動布局解決方案僅適用於安裝和卸載約束(激活和停用),無需添加或刪除約束。
我的任務總體上類似。 我需要iPhone和iPad的縱向和橫向限制。 此外,黃色和灰色視圖的位置一般應該相同,但在iPhone環境和iPad環境中黃色視圖的寬度應該不同(iPhone的屏幕占40%,iPad的屏幕占60%):
iPhone方向的約束我使用traits集合設置並為每個約束定義它應該安裝的集合。 對於iPhone,有wChR(肖像)和wChC(風景)。 或者用hAny wC:
但是對於iPad上的橫向和縱向方向,使用單個特征集合(wRhR),因此用於iPhone的方式不適合。 為了改變這些情況的約束,我提出了兩個約束集(第一個用於橫向iPad,第二個用於iPad縱向):
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *ipadLandscapeConstraints;
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *ipadPortraitConstraints;
注意:1。要執行此操作,請在故事板中選擇幾個必需的約束,並將它們連接到.m文件。 要查看向數組添加了哪些約束,請單擊左側的“+”按鈕以查看.m文件中的屬性: 2.我使用約束優先級來解決iPad的約束沖突
最后,我實現了configConstraints
方法,根據iPad方向切換約束集,並覆蓋了viewWillTransitionToSize
方法:
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[self configConstraints];
}
- (void)configConstraints {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// iPad landscape orientation
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
[NSLayoutConstraint deactivateConstraints:self.ipadPortraitConstraints];
[NSLayoutConstraint activateConstraints:self.ipadLandscapeConstraints];
}
// iPad portrait orientation
else {
[NSLayoutConstraint deactivateConstraints:self.ipadLandscapeConstraints];
[NSLayoutConstraint activateConstraints:self.ipadPortraitConstraints];
}
[self.view layoutIfNeeded];
}
}
可能需要在視圖加載或出現的其他地方調用configConstraints
方法,但基本思想如上所述。
將這兩個視圖放在堆棧視圖中並更改堆棧視圖的軸方向要容易得多。
我輕松實現這一目標的唯一方法是,它適用於iPad和iPhone,通過編程方式實現。 這是在Xcode 10.2中使用Swift 5.0完成的。
在ViewController中,根據方向定義要更改的兩個視圖:
@IBOutlet weak var raceInfoView: UIStackView!
@IBOutlet weak var raceListView: UITableView!
然后定義在故事板中始終保持不變的約束,並定義將在ViewController中更改的約束。
private var portraitRaceInfoViewTrailing: NSLayoutConstraint!
private var portraitRaceInfoViewBottom: NSLayoutConstraint!
private var portraitRaceListViewLeading: NSLayoutConstraint!
private var landscapeRaceInfoViewTrailing: NSLayoutConstraint!
private var landscapeRaceInfoViewBottom: NSLayoutConstraint!
private var landscapeRaceListViewTop: NSLayoutConstraint!
接下來,初始化約束,我將它放在viewDidLoad中,但它可能放在其他地方。
override func viewDidLoad() {
super.viewDidLoad()
portraitRaceInfoViewTrailing = NSLayoutConstraint(
item: racesView as Any, attribute: NSLayoutConstraint.Attribute.trailing,
relatedBy: NSLayoutConstraint.Relation.equal,
toItem: raceInfoView, attribute: NSLayoutConstraint.Attribute.trailing,
multiplier: 1, constant: 0)
portraitRaceInfoViewBottom = NSLayoutConstraint(
item: raceListView as Any, attribute: NSLayoutConstraint.Attribute.top,
relatedBy: NSLayoutConstraint.Relation.equal,
toItem: raceInfoView, attribute: NSLayoutConstraint.Attribute.bottom,
multiplier: 1, constant: 0)
portraitRaceListViewLeading = NSLayoutConstraint(
item: raceListView as Any, attribute: NSLayoutConstraint.Attribute.leading,
relatedBy: NSLayoutConstraint.Relation.equal,
toItem: racesView, attribute: NSLayoutConstraint.Attribute.leading,
multiplier: 1, constant: 0)
landscapeRaceInfoViewTrailing = NSLayoutConstraint(
item: raceListView as Any, attribute: NSLayoutConstraint.Attribute.leading,
relatedBy: NSLayoutConstraint.Relation.equal,
toItem: raceInfoView, attribute: NSLayoutConstraint.Attribute.trailing,
multiplier: 1, constant: 0)
landscapeRaceInfoViewBottom = NSLayoutConstraint(
item: raceInfoView as Any, attribute: NSLayoutConstraint.Attribute.bottom,
relatedBy: NSLayoutConstraint.Relation.equal,
toItem: racesView, attribute: NSLayoutConstraint.Attribute.bottom,
multiplier: 1, constant: 0)
landscapeRaceListViewTop = NSLayoutConstraint(
item: raceListView as Any, attribute: NSLayoutConstraint.Attribute.top,
relatedBy: NSLayoutConstraint.Relation.equal,
toItem: racesView, attribute: NSLayoutConstraint.Attribute.top,
multiplier: 1, constant: 0)
applyOrientationConstraints()
}
以編程方式聲明約束看起來有點可怕,但實際上很容易。 您可以在故事板中創建約束並查看所有值,並將正確的值復制到代碼中的正確位置。
最后在viewDidLoad中使用applyOrientationConstraints()
應用約束。
func applyOrientationConstraints() {
let orient = UIApplication.shared.statusBarOrientation
switch orient {
case .portrait:
NSLayoutConstraint.activate([portraitRaceInfoViewTrailing, portraitRaceInfoViewBottom, portraitRaceListViewLeading])
NSLayoutConstraint.deactivate([landscapeRaceInfoViewTrailing, landscapeRaceInfoViewBottom, landscapeRaceListViewTop])
break
default:
NSLayoutConstraint.deactivate([portraitRaceInfoViewTrailing, portraitRaceInfoViewBottom, portraitRaceListViewLeading])
NSLayoutConstraint.activate([landscapeRaceInfoViewTrailing, landscapeRaceInfoViewBottom, landscapeRaceListViewTop])
break
}
}
最后覆蓋viewWillTransition
以在方向更改時應用約束。
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) -> Void in
self.applyOrientationConstraints()
}, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
print("rotation completed")
})
super.viewWillTransition(to: size, with: coordinator)
}
我的兩分錢..迅捷5:
(請連接插座..)
//
// ViewController.swift
// AutoLayoutSampleOnRotation
//
// Created by ing.conti on 13/09/2019.
// Copyright © 2019 ing.conti. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var redView: UIView!
@IBOutlet weak var yellowView: UIView!
private var red_TopPortrait : NSLayoutConstraint?
private var red_TopLandscape : NSLayoutConstraint?
private var red_LeftPortrait : NSLayoutConstraint?
private var red_LeftLandscape : NSLayoutConstraint?
private var red_RightPortrait : NSLayoutConstraint?
private var red_RightLandscape : NSLayoutConstraint?
private var red_BottomPortrait : NSLayoutConstraint?
private var red_BottomLandscape : NSLayoutConstraint?
private var red_HeightPortrait : NSLayoutConstraint?
private var red_WidthLandscape : NSLayoutConstraint?
///
private var yellow_TopPortrait : NSLayoutConstraint?
private var yellow_TopLandscape : NSLayoutConstraint?
private var yellow_LeftPortrait : NSLayoutConstraint?
private var yellow_LeftLandscape : NSLayoutConstraint?
private var yellow_RightPortrait : NSLayoutConstraint?
private var yellow_RightLandscape : NSLayoutConstraint?
private var yellow_BottomPortrait : NSLayoutConstraint?
private var yellow_BottomLandscape : NSLayoutConstraint?
private let H_SpaceBetween = CGFloat(20)
private let V_SpaceBetween = CGFloat(50)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
redView.translatesAutoresizingMaskIntoConstraints = false
yellowView.translatesAutoresizingMaskIntoConstraints = false
buildConstraintsForRed()
buildConstraintsForYellow()
applyConstraints()
}
final private func buildConstraintsForRed(){
let portraitTopMargin = CGFloat(70)
let portraitLeftMargin = CGFloat(70)
let portraitRightMargin = CGFloat(70)
let landscapeTopMargin = CGFloat(70)
let landscapeLeftMargin = CGFloat(70)
let landscapeBottomMargin = CGFloat(70)
// TOP P
red_TopPortrait = NSLayoutConstraint(item: redView as Any,
attribute: .top,
relatedBy: .equal,
toItem: self.view,
attribute: .top,
multiplier: 1,
constant: portraitTopMargin)
red_TopPortrait!.identifier = "red_TopPortrait"
// LEFT-Heading P
red_LeftPortrait = NSLayoutConstraint(item: redView as Any,
attribute: .leading,
relatedBy: .equal,
toItem: self.view,
attribute: .leading,
multiplier: 1,
constant: portraitLeftMargin)
red_LeftPortrait!.identifier = "red_LeftPortrait"
// RIGHT - trailing P
red_RightPortrait = NSLayoutConstraint(item: redView as Any,
attribute: .trailing,
relatedBy: .equal,
toItem: self.view,
attribute: .trailing,
multiplier: 1,
constant: -portraitRightMargin)
red_RightPortrait!.identifier = "red_RightPortrait"
// BOTTOM: P
red_BottomPortrait = NSLayoutConstraint(item: redView as Any,
attribute: .bottom,
relatedBy: .equal,
toItem: yellowView,
attribute: .top,
multiplier: 1,
constant: -V_SpaceBetween)
red_BottomPortrait!.identifier = "red_BottomPortrait"
// HEIGHT: P
red_HeightPortrait = NSLayoutConstraint(item: redView as Any,
attribute: .height,
relatedBy: .equal,
toItem: self.view,
attribute: .height,
multiplier: 0.3,
constant: 0)
red_HeightPortrait?.identifier = "red_HeightPortrait"
//LANDSCAPE
// TOP L
red_TopLandscape = NSLayoutConstraint(item: redView as Any,
attribute: .top,
relatedBy: .equal,
toItem: self.view,
attribute: .top,
multiplier: 1,
constant: landscapeTopMargin)
red_TopLandscape!.identifier = "red_TopLandscape"
// LEFT-Heading L
red_LeftLandscape = NSLayoutConstraint(item: redView as Any,
attribute: .leading,
relatedBy: .equal,
toItem: self.view,
attribute: .leading,
multiplier: 1,
constant: landscapeLeftMargin)
red_LeftLandscape!.identifier = "red_LeftLandscape"
// RIGHT - trailing L
red_RightLandscape = NSLayoutConstraint(item: redView as Any,
attribute: .trailing,
relatedBy: .equal,
toItem: yellowView,
attribute: .leading,
multiplier: 1,
constant: -H_SpaceBetween)
red_RightLandscape!.identifier = "red_RightLandscape"
// BOTTOM: L
red_BottomLandscape = NSLayoutConstraint(item: redView as Any,
attribute: .bottom,
relatedBy: .equal,
toItem: self.view,
attribute: .bottom,
multiplier: 1,
constant: -landscapeBottomMargin)
red_BottomLandscape?.identifier = "red_BottomLandscape"
// Width L:
red_WidthLandscape = NSLayoutConstraint(item: redView as Any,
attribute: .width,
relatedBy: .equal,
toItem: self.view,
attribute: .width,
multiplier: 0.3,
constant: 0)
red_WidthLandscape!.identifier = "red_WidthLandscape"
}
final private func buildConstraintsForYellow(){
let portraitLeftMargin = CGFloat(20)
let portraitRightMargin = CGFloat(20)
//let portraitHorizMargin = CGFloat(100)
let portraitBottomMargin = CGFloat(20)
let landscaspeTopMargin = CGFloat(20)
let landscaspeRightMargin = CGFloat(20)
let landscapeBottomMargin = CGFloat(20)
// TOP P
yellow_TopPortrait = NSLayoutConstraint(item: yellowView as Any,
attribute: .top,
relatedBy: .equal,
toItem: redView,
attribute: .bottom,
multiplier: 1,
constant: V_SpaceBetween)
yellow_TopPortrait!.identifier = "yellow_TopPortrait"
// LEFT-Heading P
yellow_LeftPortrait = NSLayoutConstraint(item: yellowView as Any,
attribute: .leading,
relatedBy: .equal,
toItem: self.view,
attribute: .leading,
multiplier: 1,
constant: portraitLeftMargin)
yellow_LeftPortrait!.identifier = "yellow_LeftPortrait"
// RIGHT - trailing P
yellow_RightPortrait = NSLayoutConstraint(item: yellowView as Any,
attribute: .trailing,
relatedBy: .equal,
toItem: self.view,
attribute: .trailing,
multiplier: 1,
constant: -portraitRightMargin)
yellow_RightPortrait!.identifier = "yellow_RightPortrait"
// BOTTOM: P
yellow_BottomPortrait = NSLayoutConstraint(item: yellowView as Any,
attribute: .bottom,
relatedBy: .equal,
toItem: self.view,
attribute: .bottom,
multiplier: 1,
constant: -portraitBottomMargin)
yellow_BottomPortrait!.identifier = "yellow_BottomPortrait"
//LANDSSCAPE
// TOP L
yellow_TopLandscape = NSLayoutConstraint(item: yellowView as Any,
attribute: .top,
relatedBy: .equal,
toItem: self.view,
attribute: .top,
multiplier: 1,
constant: landscaspeTopMargin)
yellow_TopLandscape!.identifier = "yellow_TopLandscape"
// LEFT-Heading L
yellow_LeftLandscape = NSLayoutConstraint(item: yellowView as Any,
attribute: .leading,
relatedBy: .equal,
toItem: self.redView,
attribute: .trailing,
multiplier: 1,
constant: H_SpaceBetween)
yellow_LeftLandscape!.identifier = "yellow_LeftLandscape"
// RIGHT - trailing L
yellow_RightLandscape = NSLayoutConstraint(item: yellowView as Any,
attribute: .trailing,
relatedBy: .equal,
toItem: self.view,
attribute: .trailing,
multiplier: 1,
constant: -landscaspeRightMargin)
yellow_RightLandscape!.identifier = "yellow_RightLandscape"
// BOTTOM: L
yellow_BottomLandscape = NSLayoutConstraint(item: yellowView as Any,
attribute: .bottom,
relatedBy: .equal,
toItem: self.view,
attribute: .bottom,
multiplier: 1,
constant: -landscapeBottomMargin)
yellow_BottomLandscape!.identifier = "yellow_BottomLandscape"
}
final private func removeRedConstraints() {
if let c = red_LeftPortrait {self.view.removeConstraint(c)}
if let c = red_LeftLandscape {self.view.removeConstraint(c)}
if let c = red_RightPortrait {self.view.removeConstraint(c)}
if let c = red_RightLandscape {self.view.removeConstraint(c)}
if let c = red_TopPortrait {self.view.removeConstraint(c)}
if let c = red_TopLandscape {self.view.removeConstraint(c)}
if let c = red_BottomPortrait {self.view.removeConstraint(c)}
if let c = red_BottomLandscape {self.view.removeConstraint(c)}
if let c = red_HeightPortrait {self.view.removeConstraint(c)}
if let c = red_WidthLandscape {self.view.removeConstraint(c)}
}
final private func removeYellowConstraints() {
if let c = yellow_LeftPortrait {self.view.removeConstraint(c)}
if let c = yellow_LeftLandscape {self.view.removeConstraint(c)}
if let c = yellow_RightPortrait {self.view.removeConstraint(c)}
if let c = yellow_RightLandscape {self.view.removeConstraint(c)}
if let c = yellow_TopPortrait {self.view.removeConstraint(c)}
if let c = yellow_TopLandscape {self.view.removeConstraint(c)}
if let c = yellow_BottomPortrait {self.view.removeConstraint(c)}
if let c = yellow_BottomLandscape {self.view.removeConstraint(c)}
}
final private func applyPortraitConstraint(){
removeRedConstraints()
removeYellowConstraints()
self.view.addConstraint(self.red_LeftPortrait!)
self.view.addConstraint(self.red_RightPortrait!)
self.view.addConstraint(self.red_TopPortrait!)
self.view.addConstraint(self.red_BottomPortrait!)
self.view.addConstraint(self.red_HeightPortrait!)
self.view.addConstraint(self.yellow_LeftPortrait!)
self.view.addConstraint(self.yellow_RightPortrait!)
self.view.addConstraint(self.yellow_TopPortrait!)
self.view.addConstraint(self.yellow_BottomPortrait!)
}
final private func applyLandscapeConstraint(){
removeRedConstraints()
removeYellowConstraints()
self.view.addConstraint(self.red_LeftLandscape!)
self.view.addConstraint(self.red_RightLandscape!)
self.view.addConstraint(self.red_TopLandscape!)
self.view.addConstraint(self.red_BottomLandscape!)
self.view.addConstraint(self.red_WidthLandscape!)
self.view.addConstraint(self.yellow_LeftLandscape!)
self.view.addConstraint(self.yellow_RightLandscape!)
self.view.addConstraint(self.yellow_TopLandscape!)
self.view.addConstraint(self.yellow_BottomLandscape!)
}
final private func applyConstraints(){
let orient = UIApplication.shared.statusBarOrientation
switch orient {
case .portrait:
print("Portrait")
self.applyPortraitConstraint()
break
// Do something
default:
print("LandScape")
// Do something else
self.applyLandscapeConstraint()
break
}
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) -> Void in
self.applyConstraints()
}, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
print("rotation completed")
})
super.viewWillTransition(to: size, with: coordinator)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.