2010-08-09 13 views
33

मैं फ़्रेमलेआउट के उप-वर्ग पर काम कर रहा हूं जो अपने सभी बच्चों को 90 डिग्री से घूमने वाला माना जाता है। मैं एंड्रॉइड 2.1 और नीचे में लैंडस्केप-केवल कैमरे की सीमा को पार करने के लिए कर रहा हूं, गतिविधि को परिदृश्य में रखकर, लेकिन मेरे कैमरे को ओवरले में इस फ़्रेमेलआउट ओवरले में रखकर ऐसा लगता है कि यह पोर्ट्रेट (this is how Layar does it) था इसे पूरा करने के लिए, मैं दृश्यों को घुमाने के लिए Jeff Sharkey's code का अनुकूलन कर रहा हूं। मेरी समस्या यह है कि मैं Framelayout घुमा सकते हैं, लेकिन मैं नए आयामों से मेल खाने के लिए इसका आकार बदल नहीं सकता। तो मेरे जी 1 पर, लैंडस्केप में 480x320 कैमरे के दृश्य पर 320x480 पोर्ट्रेट व्यू के बजाय, मुझे बीच में 320x320 बॉक्स मिलता है जो पक्षियों के साथ मेरे पोर्ट्रेट व्यू को दिखाता है।घुमाएं देखें पदानुक्रम 90 डिग्री

public class RotateLayout extends FrameLayout { 
    private Matrix mForward = new Matrix(); 
    private Matrix mReverse = new Matrix(); 
    private float[] mTemp = new float[2]; 

    public RotateLayout(Context context) { 
     super(context); 
    } 

    public RotateLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 

    } 


    /* (non-Javadoc) 
    * @see android.widget.FrameLayout#onMeasure(int, int) 
    */ 
    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     //This didn't work: 
     //super.onMeasure(heightMeasureSpec, widthMeasureSpec); 
    } 

    /* (non-Javadoc) 
    * @see android.widget.FrameLayout#onSizeChanged(int, int, int, int) 
    */ 
    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     super.onSizeChanged(w, h, oldw, oldh); 
    } 

    @Override 
    protected void dispatchDraw(Canvas canvas) { 
     canvas.rotate(270, getWidth()/2, getHeight()/2); 
     //This code will stretch the canvas to accommodate the new screen size. This is not what I want. 
     //float scaleX=(float)getHeight()/getWidth(); 
     //float scaleY=(float)getWidth()/getHeight(); 
     //canvas.scale(scaleX, scaleY, getWidth()/2, getHeight()/2); 
     mForward = canvas.getMatrix(); 
     mForward.invert(mReverse); 
     canvas.save(); 
     canvas.setMatrix(mForward); //This is the matrix we need to use for proper positioning of touch events 
     super.dispatchDraw(canvas); 
     canvas.restore(); 
    } 

    @Override 
    public boolean dispatchTouchEvent(MotionEvent event) { 
     final float[] temp = mTemp; 
     temp[0] = event.getX(); 
     temp[1] = event.getY(); 

     mReverse.mapPoints(temp); 

     event.setLocation(temp[0], temp[1]); 
     return super.dispatchTouchEvent(event); 
    } 
} 

मैं OnMeasure अधिभावी एक्स और देखें की Y आयाम स्विच करने के लिए कोशिश की है, लेकिन नहीं है कि काम करने के लिए प्राप्त करने में सक्षम किया गया है:

यहाँ मेरी कोड अब तक है। कोई भी सहायता जो आप प्रदान कर सकते हैं उसकी बहुत सराहना की जाती है।

+0

हाय, क्या आपने इसे किसी भी तरह हल किया? – fhucho

+0

नहीं - अंतिम समाधान उपरोक्त कोड का उपयोग करना था और इनमें से प्रत्येक में से प्रत्येक को लपेटकर बटन, टेक्स्टव्यू इत्यादि को अलग-अलग घुमाएं। यह बहुत सुरुचिपूर्ण नहीं है, लेकिन यह काम करता है। – QRohlf

+2

मेरा मानना ​​है कि 'प्रेषण टचएवेंट()' के अंदर आपको 'getX()' और 'getY()' के बजाय 'getRawX()' और 'getRawY()' का उपयोग करना चाहिए। यह किसी भी दर पर मेरे लिए बेहतर काम करता है। मेरा विचार वर्ग है, fwiw। –

उत्तर

39

मुझे एक ही समस्या थी और इसे हल करने में कामयाब रहा। प्रत्येक दृश्य या लेआउट को हाथ से घूर्णन करने के बजाय, मैंने एक लेआउटएनिमेशन कंट्रोलर का उपयोग किया।

पहले,/में एक फ़ाइल जगह रेस/anim/rotation.xml

<?xml version="1.0" encoding="utf-8"?> 
<rotate 
xmlns:android="http://schemas.android.com/apk/res/android" 
    android:fromDegrees="0" 
    android:toDegrees="-90" 
    android:pivotX="50%" 
    android:pivotY="50%" 
    android:duration="0" android:fillAfter="true"> 
</rotate> 

तो कहा जाता है, अपनी गतिविधि के onCreate में,

@Override 
    public void onCreate(Bundle icicle) { 
    super.onCreate(icicle); 

    setContentView(R.layout.myscreen); 

    Animation rotateAnim = AnimationUtils.loadAnimation(this, R.anim.rotation); 
    LayoutAnimationController animController = new LayoutAnimationController(rotateAnim, 0); 
    FrameLayout layout = (FrameLayout)findViewById(R.id.MyScreen_ContentLayout); 
    layout.setLayoutAnimation(animController); 
} 

कर आप तत्वों है कि ऊपर झूठ को घुमाने के लिए चाहते हैं आपका कैमरा पूर्वावलोकन दृश्य (SurfaceHolder), बस SurfaceHolder के ऊपर फ़्रेमलेआउट रखें, अपने सभी तत्वों को उस फ्रेमलेआउट में रखें और लेआउट "MyScreen_ContentLayout" को कॉल करें। किया हुआ।

आशा है कि किसी को बाहर की मदद की, मुझे सब कुछ एक साथ पाने के लिए काफी समय लगा।

+0

यह एक दिलचस्प समाधान है। इसके साथ सामना करने वाली एकमात्र समस्या यह है कि घुमावदार लेआउट का विस्तार नहीं होता है। तो उदाहरण के लिए, यदि आपके पास 2 छवियों के साथ एक लेआउट है - 1 स्क्रीन के शीर्ष पर और 1 बहुत नीचे है। लेआउट को घुमाए जाने के बाद, 2 छवियों के बीच की दूरी एक ही रहेगी - घुमावदार दृश्य के ऊपर/नीचे होने के विस्तार के बजाय वे बीच में कहीं भी होंगी। –

+0

आपका विचार धन्यवाद/क्या आप अधिक विस्तार से कह सकते हैं "बस सतहफॉलर के ऊपर फ़्रेमलेआउट रखें" मैं इसे कैसे कर सकता हूं? – LTEHUB

+1

अपने लेआउट xml फ़ाइल में, फ़्रेमेलआउट बनाएं और इसे रखें ताकि यह सतह धारक के ऊपर स्थित हो (framelayout पूरी तरह से सतह धारक को कवर करता है)। – Georg

0

मुझे लगता है कि आप अपने onMeasure में एक पंक्ति भूल गया।

@Override 
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    super.onMeasure(heightMeasureSpec, widthMeasureSpec); 
    setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); 
} 

एक ऊर्ध्वाधर seekbar यहाँ कोड से लिया: How can I get a working vertical SeekBar in Android?

आप getMeasuredHeight() के साथ बेला को उसे अपनी स्क्रीन के सही आकार बनाने के लिए आवश्यकता हो सकती है।

6

एपीआई स्तर 11 का उपयोग करके और बाद में आप प्रोग्राम्सैटिक रूप से दृश्य के घूर्णन को बदलने के लिए setRotation(degreesFloat); विधि का उपयोग कर सकते हैं, या आप एक्सएमएल विशेषता android:rotation="" का उपयोग अपने एक्सएमएल में बदलने के लिए कर सकते हैं। दृश्य के घूर्णन के केवल एक्स या वाई मानों को बदलने के लिए विधियों/विशेषताओं भी हैं: Android Docs - View (setRotation)

तो आजकल जब तक आप ऊपर एपीआई स्तर 11 या उपयोग कर रहे हैं, तो आप एक आवरण लेआउट नोड के लिए रोटेशन लागू करने के लिए सक्षम होना चाहिए। हालांकि, घूर्णन के बाद इच्छित आयामों से मेल खाने के लिए आपको शायद शीर्ष-स्तरीय लेआउट के आयामों को भी बदलना होगा। अर्थात। यदि आपके पास पोर्ट्रेट व्यू w/आयाम 800x1280 है, तो आपको परिदृश्य में घुमाने के बाद इसे लाइन करने के लिए उन्हें 1280x800 में बदलना होगा।

0

आपके विचार जड़ की कतरन बच्चों को बंद करके देखें: अपने RotateLayout की मूल पर और अपने RotateLayout की onMeasure विधि में setClipChildren(false) फोन इन पंक्तियों डाल:

super.onMeasure(heightMeasureSpec, widthMeasureSpec); 
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); 

मैं मूल रूप से आप के रूप में ही समस्या आ रही है और मैंने अभी भी अपने समाधान का परीक्षण नहीं किया है - मैं कल इसे करूँगा और बताउंगा कि यह सही तरीके से काम कर रहा है या नहीं।

+0

के साथ ऐसा कर रहा हूं ऐसा लगता है कि 'setClipChildren (false)' काम नहीं करता है। मुझे आश्चर्य है क्योंकि... – DoDo

1

यह वही है सामान्य रूप में मेरे लिए काम किया है की तरह।

private void init() { 
    setRotation(90f); 
} 

public YourViewOrViewGroup(final Context context) { 
    super(context); 
    init(); 
} 

... (all the View/ViewGroup constructors) ... 

@Override 
protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b) { 
    super.onLayout(changed, l, t, r, b); 

    final int width = getWidth(); 
    final int height = getHeight(); 
    final int offset = Math.abs(width - height)/2; 
    setTranslationX(-offset); 
    setTranslationY(offset); 
} 

@Override 
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 
    super.onMeasure(heightMeasureSpec, widthMeasureSpec); 
} 

आप क्या करना चाहते क्या स्वैप ऊंचाई के साथ चौड़ाई है और फिर X & वाई ऑफसेट डाल इतना है कि दृश्य रोटेशन के बाद पूर्ण स्क्रीन हो जाता है।

उपर्युक्त 'परिदृश्य'-घुमावदार संस्करण है। एक परिदृश्य उलटा पाने के लिए बस 270-डिग्री रोटेशन लागू करें। आप स्निपेट के भीतर कोड को संशोधित करने या रोटेशन के बाहर एक और अधिक सामान्य तरीके से

final YourViewOrViewGroup layout = inflater.inflate(...); 
if (currentOrientation.isInverted()) { 
    layout.setRotation(layout.getRotation + 180f); 
} 

इस तरह से आप एक्सएमएल परिभाषा के दायरे में घुमाया देखें/ViewGroup एम्बेड और 'पोर्ट' और 'को बढ़ाने के लिए सक्षम हैं लागू होते हैं, यानी या तो कर सकते हैं भूमि अभिविन्यास बदलते समय भूमि 'संस्करण, लेकिन यह इस विषय से बाहर लगता है।

संपादित करें: वास्तव में ऑफसेट सेटिंग को कम से कम एक लेआउट पास खत्म होने तक रोकना बेहतर होता है। यह तथ्य इस तथ्य के कारण है कि मेरे मामले में पहले मापन() के बाद दृश्य खींचा जाएगा (ऑफसेट सेट होने से पहले)। आखिरकार इसे गड़बड़ाने के रूप में अनुभव किया जा सकता है क्योंकि दृश्य/लेआउट पहली बार अंतिम सीमाओं में नहीं खींचा जाएगा। (स्निपेट अपडेट किया गया)

संबंधित मुद्दे