2012-06-18 21 views
7

मेरा एप्लिकेशन PortraitUpsideDown को छोड़कर सभी ओरिएंटेशन का समर्थन करता है। मेरे दृश्य पदानुक्रम में मेरे पास शीर्ष दृश्य में एक उपन्यास के रूप में एक AVCaptureVideoPreviewLayer है जो UIImageView है। इसके बाद नीचे पदानुक्रम नियंत्रण में कई ओवरले दृश्य दिख रहे हैं।AVCaptureVideoPreviewLayer में autorotation को कैसे संभालें?

ओवरले दृश्य अभिविन्यास परिवर्तनों के साथ ठीक से काम कर रहे हैं, लेकिन मैं इस AVCaptureVideoPreviewLayer के साथ कैसे नहीं रहूं। मैं इसे कैमरा ऐप में व्यवहार करना चाहता हूं, ताकि पूर्वावलोकन लेयर अभी भी रहता है और नियंत्रण आसानी से पुनर्गठित होते हैं। अभी जब मुख्य दृश्य अभिविन्यास परिवर्तन पर घुमाया गया है, तो मेरी पूर्वावलोकन परत भी घूमती है, जिसका अर्थ है कि परिदृश्य में यह चित्र दृश्य में रहता है, स्क्रीन का केवल एक हिस्सा लेता है और कैमरे की तस्वीर 90 डिग्री से घूमती है। मैंने पूर्वावलोकन परत को मैन्युअल रूप से घुमाने में कामयाब रहा है, लेकिन उसके बाद यह अभिविन्यास परिवर्तन एनीमेशन है, जो एनीमेशन के दौरान थोड़ी देर के लिए पृष्ठभूमि को देखा जाता है।

तो पूर्वावलोकन करते समय नियंत्रण को स्वत: व्यवस्थित करने का सही तरीका क्या है अभी भी रहना है?

+1

समान समस्या था। एक _obvious_ समाधान दुर्भाग्य से उपलब्ध नहीं है: मैं (KVO के साथ) का पालन करने के उम्मीद थी 'किस्मत के बिना दृश्य की परत की' presentationLayer' की transform' - कुंजी-मान-अवलोकन एनीमेशन रनटाइम के दौरान उपलब्ध नहीं है। आपके द्वारा समान समाधान (संभवतः) का उपयोग करके समाप्त हो गया: पूर्वावलोकन परत को 'UIView' में मैन्युअल रूप से घूर्णन करने के लिए एम्बेड करना। –

+2

हां, मैं पूर्वावलोकनलेयर युक्त दृश्य के मैन्युअल रोटेशन के साथ भी समाप्त हुआ। यह बहुत जटिल नहीं हो गया। मैं CGAffineTransformMakeRotation() लागू करता हूं और फिर फ्रेम को सही आकार में बदलता हूं। लेकिन अब मेरे पास बिल्कुल वही व्यवहार है जो मैं चाहता हूं। – BartoNaz

+0

@BartoNaz मैं अब कुछ दिनों के लिए इस के साथ संघर्ष कर दिया गया है और सब कुछ मैं कोशिश मुझे camera.app जहां AVCaptureVideoPreviewLayer किसी दृश्य में लॉक रहता है के प्रभाव को नहीं देता है, और इसकी एनिमेटेड रोटेशन नहीं करता है। क्या आप कृपया इस प्रश्न के उत्तर के रूप में अपना कामकाजी कोड स्निपेट प्रदान कर सकते हैं? धन्यवाद। –

उत्तर

5

मेरे कार्यान्वयन में मैंने अपने दृश्य के लिए UIView को उपclassed है जिसे मैं घूमना चाहता हूं और इस दृश्य के लिए दृश्य नियंत्रक जैसे कुछ एनएसओब्जेक्ट का एक उप-वर्ग है।

इस दृश्य में नियंत्रक मैं अभिविन्यास के परिवर्तन से संबंधित सभी चेक करता हूं, निर्णय लेता हूं कि मुझे अपने लक्षित दृश्य के अभिविन्यास को बदलना चाहिए, और यदि हां, तो मैं इसके अभिविन्यास को बदलने के लिए अपने विचार की विधि को कॉल करता हूं।

सबसे पहले हमें पोर्ट्रेट मोड में पूरे एप्लिकेशन इंटरफ़ेस के अभिविन्यास को ठीक करने की आवश्यकता है, ताकि हमारे ACCaptureVideoPreviewLayer हमेशा स्थिर रहें। यह MainViewController.h में किया जाता है:

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation` 
{ 
    return interfaceOrientation==UIInterfaceOrientationPortrait; 
} 

यह पोर्ट्रेट को छोड़कर सभी झुकाव को नहीं देता है।

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(orientationChanged) name:UIDeviceOrientationDidChangeNotification object:nil]; 

मैं अपने ViewController की (void)awakeFromNib विधि में इन पंक्तियों के रख:

आदेश में हमारे कस्टम के लिए ViewController डिवाइस अभिविन्यास के परिवर्तन हम इसे इसी सूचनाओं के एक पर्यवेक्षक बनाने की जरूरत है पर नज़र रखने के लिए सक्षम हो। इसलिए प्रत्येक बार डिवाइस अभिविन्यास बदल जाता है, दृश्य नियंत्रक की विधि orientationChanged कहा जाएगा।

इसका उद्देश्य यह जांचना है कि डिवाइस का नया अभिविन्यास क्या है, डिवाइस का अंतिम अभिविन्यास क्या था और यह तय करना है कि इसे बदलना है या नहीं। यहां कार्यान्वयन है:

if(UIInterfaceOrientationPortraitUpsideDown==[UIDevice currentDevice].orientation || 
    lastOrientation==(UIInterfaceOrientation)[UIDevice currentDevice].orientation) 
    return; 
    [[UIApplication sharedApplication]setStatusBarOrientation:[UIDevice currentDevice].orientation animated:NO]; 

    lastOrientation=[UIApplication sharedApplication].statusBarOrientation; 
    [resultView orientationChanged]; 

यदि अभिविन्यास पहले या PortraitUpsideDown में समान है तो कुछ भी नहीं करें। अन्यथा यह स्टेटस बार अभिविन्यास को उचित पर सेट करता है, ताकि जब कोई इनकमिंग कॉल या ओसिफिकेशन हो, तो यह स्क्रीन के उचित पक्ष पर दिखाई देगा। और फिर मैं लक्ष्य दृश्य में भी विधि को कॉल करता हूं जहां नए अभिविन्यास के लिए सभी संबंधित परिवर्तन किए जाते हैं, जैसे घूर्णन, आकार बदलना, इस दृश्य में इंटरफ़ेस के अन्य तत्वों को नए अभिविन्यास से संबंधित करना।

Float32 angle=0.f; 
UIInterfaceOrientation orientation=[UIApplication sharedApplication].statusBarOrientation; 

switch (orientation) { 
    case UIInterfaceOrientationLandscapeLeft: 
     angle=-90.f*M_PI/180.f; 
     break; 
    case UIInterfaceOrientationLandscapeRight: 
      angle=90.f*M_PI/180.f; 
     break; 
    default: angle=0.f; 
     break; 
} 
if(angle==0 && CGAffineTransformIsIdentity(self.transform)) return; 

CGAffineTransform transform=CGAffineTransformMakeRotation(angle); 

[UIView beginAnimations:@"rotateView" context:nil]; 
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; 
[UIView setAnimationDuration:0.35f]; 

self.transform=transform; 

[UIView commitAnimations]; 
बेशक

यहाँ आप अनुवाद, कि नए उन्मुखीकरण का जवाब और चेतन करने की जरूरत है अपने इंटरफेस के विभिन्न दृश्यों की स्केलिंग की तरह कोई अन्य परिवर्तन जोड़ सकते हैं:

यहाँ लक्ष्य को ध्यान में रखते orientationChanged के कार्यान्वयन है उन्हें।

इसके अलावा आपको इसके लिए दृश्य नियंत्रक की आवश्यकता नहीं हो सकती है, लेकिन बस अपने दृश्य के वर्ग में ही करें। आशा है कि सामान्य विचार स्पष्ट है।

इसके अलावा उन्मुखीकरण में परिवर्तन के लिए हो रही अधिसूचना को रोकने के लिए मत भूलना जब आप उन्हें पसंद की जरूरत नहीं है:

[[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; 
[[UIDevice currentDevice]endGeneratingDeviceOrientationNotifications]; 
0

मुख्य समस्या है कि जब मैं सूचना मिलने पर स्थिति बार अभी तक घुमाया नहीं है, तो वर्तमान मूल्य की जांच वास्तव में घूर्णन से पहले मूल्य देते हैं।

-(void) handleNotification:(NSNotification *) notification 
{  
    (void) [NSTimer scheduledTimerWithTimeInterval:(2.0) 
              target:self 
              selector:@selector(orientationChanged) 
              userInfo:nil 
              repeats:NO ] ; 
} 

कोड के बाकी BartoNaz से एक है: तो मैं विधि है कि statusbarorientation जांच करें और मेरा subview घूमता कॉल करने से पहले एक छोटे से देरी (यहाँ 2 सेकंड) जोड़ा गया।

+0

नीचे एक जवाब मुझे यकीन है कि अगर यह सही है नहीं कर रहा हूँ के रूप में अपने समाधान प्रदान करें। यह वास्तव में इस विधि का विचार है, कि स्टेटसबार स्वयं ही घूमता नहीं है। और आप स्टेटसबार के वर्तमान अभिविन्यास की जांच नहीं करते हैं। आप डिवाइस के अभिविन्यास की जांच कर रहे हैं और इस विधि को कॉल करते समय पिछली बार अभिविन्यास के साथ तुलना करें। और जब आपके विधि ओरिएंटेशन बदलने का फैसला करता है, यह इस परिवर्तन मैन्युअल करता है, को फोन करके '[[UIApplication sharedApplication] setStatusBarOrientation: [UIDevice currentDevice] .orientation एनिमेटेड: NO];' – BartoNaz

+0

आप स्थिति पट्टी उन्मुखीकरण के बजाय डिवाइस अभिविन्यास यहाँ का उपयोग करना चाहिए । –

1

iOS 8 समाधान:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator { 
    if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft) { 
     self.layer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeLeft; 
    } else { 
     self.layer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight; 
    } 
} 
अपने सेटअप कोड में

:

self.layer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session]; 
self.layer.videoGravity = AVLayerVideoGravityResizeAspectFill; 
if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft) { 
    self.layer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeLeft; 
} else { 
    self.layer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight; 
} 
संबंधित मुद्दे