2012-01-24 26 views
62

करने के लिए जिस तरह से मैं बार देखा गया है जो अनिवार्य रूप LinearLayouts हैं का एक समूह प्रदर्शित करने के लिए एक GridView उपयोग कर रहा हूँ। मैं LinearLayouts चाहता हूं कि सभी स्क्वायर हों, लेकिन मैं उन्हें गतिशील रूप से आकार देना चाहता हूं - यानी, दो कॉलम हैं और मैं स्क्रीन के आकार के आधार पर LinearLayouts चाहता हूं लेकिन वर्ग बना रहता हूं। क्या xml लेआउट के माध्यम से ऐसा करने का कोई तरीका है या क्या मुझे प्रोग्रामिंग की ऊंचाई और चौड़ाई निर्धारित करना है?सरल गतिशील लेकिन वर्ग लेआउट

+2

इसे देखें http://www.gadgetsaint.com/tips/dynamic-square-rectangular-layouts-android/#.WRRjMvl96Hs – ASP

उत्तर

39

एक्सएमएल में कुछ भी नहीं है जो आपको चौड़ाई और ऊंचाई गुणों को जोड़ने देगा। शायद ऐसा करने के लिए सबसे आसान काम LinearLayout उपवर्ग और ओवरराइड onMeasure

@Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    int width = MeasureSpec.getSize(widthMeasureSpec); 
    int height = MeasureSpec.getSize(heightMeasureSpec); 
    int size = width > height ? height : width; 
    setMeasuredDimension(size, size); 
} 

मैं इस का उपयोग किया है विचारों कि हमेशा वर्ग से पहले कर रहे हैं बनाने के लिए है। यह अभी भी LinearLayout के लिए काम करना चाहिए।

अधिक जानकारी यह कर में मदद मिलेगी: http://developer.android.com/guide/topics/ui/custom-components.html http://developer.android.com/reference/android/view/View.MeasureSpec.html

+0

हाँ, मैंने कुछ ऐसा ही किया। धन्यवाद! – Catherine

+1

यदि यह आपके लिए काम करता है, तो क्या आप इसे सही उत्तर के रूप में चिह्नित कर सकते हैं? –

+0

ठीक है, मैं एक समाधान पर पहुंचा कि इसी तरह, यह थोड़ा अलग है, और मैं इसे मेजर के साथ काम नहीं कर सका, इसलिए मुझे यकीन नहीं है कि यह कोड स्निपेट मेरे लिए काम करेगा। – Catherine

90

वर्ग GridView मदों के लिए एक स्वच्छ समाधान RelativeLayout या LinearLayout का विस्तार करने और ओवरराइड onMeasure इसलिए की तरह है:

@Override 
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    super.onMeasure(widthMeasureSpec, widthMeasureSpec); 
} 
+2

यह setMeasuredDimension() का उपयोग करने के बजाय माप spec का उपयोग कर रहा है ताकि यह अच्छा हो। लेकिन यह बहुत लचीला नहीं है क्योंकि यह हमेशा चौड़ाई लेता है। – Adam

+2

जैसा कि @ डेविड मेरिमान ने उपरोक्त कहा है, यदि दृश्य लंबा है, तो यह दृश्य देखने के हिस्से को काटकर दृश्य क्षेत्र के नीचे विस्तारित करेगा। – vcapra1

+0

अजीब समाधान! –

0

यहाँ एक समाधान है जो सभी लेआउट पैरामीटर के लिए काम करता है जिन्हें देखने या देखने के लिए सेट किया जा सकता है:

int width = MeasureSpec.getSize(widthMeasureSpec); 
    int height = MeasureSpec.getSize(heightMeasureSpec); 
    int widthDesc = MeasureSpec.getMode(widthMeasureSpec); 
    int heightDesc = MeasureSpec.getMode(heightMeasureSpec); 
    int size = 0; 
    if (widthDesc == MeasureSpec.UNSPECIFIED 
      && heightDesc == MeasureSpec.UNSPECIFIED) { 
     size = DP(defaultSize); // Use your own default size, in our case 
           // it's 125dp 
    } else if ((widthDesc == MeasureSpec.UNSPECIFIED || heightDesc == MeasureSpec.UNSPECIFIED) 
      && !(widthDesc == MeasureSpec.UNSPECIFIED && heightDesc == MeasureSpec.UNSPECIFIED)) { 
        //Only one of the dimensions has been specified so we choose the dimension that has a value (in the case of unspecified, the value assigned is 0) 
     size = width > height ? width : height; 
    } else { 
        //In all other cases both dimensions have been specified so we choose the smaller of the two 
     size = width > height ? height : width; 
    } 
    setMeasuredDimension(size, size); 

चीयर्स

+0

दोनों तर्कों में Math.min (widthMeasureSpec, heightMeasureSpec) के मान को पारित करता है। इस उत्तर में कुछ रोचक विशेषताएं हैं और संभावित रूप से अधिक मजबूत है, लेकिन काम की ज़रूरत है और माप चश्मे का निर्माण करना चाहिए जो setMeasuredDimension() की बजाय super.onMeasure() को पारित किया जाना चाहिए क्योंकि यह विभिन्न प्रकार के सुपर क्लास की अनुमति देगा। – Adam

34

मैं इस तरह से किया है:

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    int widthMode = MeasureSpec.getMode(widthMeasureSpec); 
    int widthSize = MeasureSpec.getSize(widthMeasureSpec); 
    int heightMode = MeasureSpec.getMode(heightMeasureSpec); 
    int heightSize = MeasureSpec.getSize(heightMeasureSpec); 

    int size; 
    if(widthMode == MeasureSpec.EXACTLY && widthSize > 0){ 
     size = widthSize; 
    } 
    else if(heightMode == MeasureSpec.EXACTLY && heightSize > 0){ 
     size = heightSize; 
    } 
    else{ 
     size = widthSize < heightSize ? widthSize : heightSize; 
    } 

    int finalMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); 
    super.onMeasure(finalMeasureSpec, finalMeasureSpec); 
} 
इस कार्यान्वयन के साथ

, अपने लेआउट वर्ग हो जाएगा, चौड़ाई और ऊंचाई के बीच कम आकार संभालने। और इसे गतिशील मानों के साथ भी सेट किया जा सकता है, जैसे लाइनरलायआउट के अंदर वजन का उपयोग करना।

+0

"ऑनमेजर" विधि को कक्षा में ओवरराइड किया जाना है जो ग्रिड व्यू का विस्तार करता है? –

+0

कक्षा में टीटी का ओवर्रिडन आप इसे वर्ग बनाना चाहते हैं। प्रश्न के मामले में, यह GridView के अंदर LinearLayouts है। –

+0

इसने मुझे StaggeredGridLayout में स्क्वायर व्यू का उपयोग करने में कुछ अजीब मुद्दों को ठीक करने में मदद की। मेरा और अधिक निष्पक्ष कार्यान्वयन पर्याप्त नहीं था। धन्यवाद! Super.onMeasure को दो बार कॉल करने के बजाय – Peterdk

7

हम एक बहुत ही आसान तरीका के साथ यह कर सकते हैं - बस दो बार super.onMeasure() कहते हैं।

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    int width = getMeasuredWidth(); 
    int height = getMeasuredHeight(); 
    int squareLen = width; 
    if (height > width) { 
     squareLen = height; 
    } 
    super.onMeasure(
     MeasureSpec.makeMeasureSpec(squareLen, MeasureSpec.EXACTLY), 
     MeasureSpec.makeMeasureSpec(squareLen, MeasureSpec.EXACTLY)); 
} 

super.onMeasure() दो बार फोन करने से, यह ड्राइंग प्रक्रिया के संदर्भ में कम कुशल है, लेकिन यह लेआउट मुद्दों को ठीक करने के लिए अन्य उत्तर पैदा कर सकता है कि एक आसान तरीका है।

+2

, दूसरी बार आपको केवल सेटमैसर्ड डिमेंशन (स्क्वायरलेन, स्क्वायरलेन) कॉल करने की आवश्यकता है; – user3802077

+0

कॉलिंग 'super.onMeasure() 'दो बार यह सुनिश्चित करता है कि दृश्य के नए आकार को लेआउट सही ढंग से किया जाता है।इसके बिना हमें एक अलग तरीके से एक लेआउट ट्रिगर करने या गलत लेआउट से निपटने की जरूरत है। –

1

मेरे सुझाव एक कस्टम लेआउट वर्ग कि FrameLayout से विरासत बनाने के लिए है। OnMeasure() विधि को ओवरराइड करें और उस स्क्वायरफ्रेमलेआउट के अंदर जो भी नियंत्रण आप स्क्वायर बनना चाहते हैं उसे रखें।

यह है कि यह कैसे Xamarin.Android में किया है है: निम्नलिखित तरीके

public class SquareFrameLayout : FrameLayout 
{ 
    private const string _tag = "SquareFrameLayout"; 

    public SquareFrameLayout(Android.Content.Context context):base(context) {} 
    public SquareFrameLayout(IntPtr javaReference, Android.Runtime.JniHandleOwnership transfer):base(javaReference, transfer) {} 
    public SquareFrameLayout(Android.Content.Context context, IAttributeSet attrs):base(context, attrs) {} 
    public SquareFrameLayout(Android.Content.Context context, IAttributeSet attrs, int defStyleAttr):base(context, attrs, defStyleAttr) {} 
    public SquareFrameLayout(Android.Content.Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes):base(context, attrs, defStyleAttr, defStyleRes) {} 

    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    { 
     var widthMode = MeasureSpec.GetMode(widthMeasureSpec); 
     int widthSize = MeasureSpec.GetSize(widthMeasureSpec); 
     var heightMode = MeasureSpec.GetMode(heightMeasureSpec); 
     int heightSize = MeasureSpec.GetSize(heightMeasureSpec); 

     int width, height; 

     switch (widthMode) 
     { 
      case MeasureSpecMode.Exactly: 
       width = widthSize; 
       break; 
      case MeasureSpecMode.AtMost: 
       width = Math.Min(widthSize, heightSize); 
       break; 
      default: 
       width = 100; 
       break; 
     } 

     switch (heightMode) 
     { 
      case MeasureSpecMode.Exactly: 
       height = heightSize; 
       break; 
      case MeasureSpecMode.AtMost: 
       height = Math.Min(widthSize, heightSize); 
       break; 
      default: 
       height = 100; 
       break; 
     } 

     Log.Debug(_tag, $"OnMeasure({widthMeasureSpec}, {heightMeasureSpec}) => Width mode: {widthMode}, Width: {widthSize}/{width}, Height mode: {heightMode}, Height: {heightSize}/{height}"); 
     var size = Math.Min(width, height); 
     var newMeasureSpec = MeasureSpec.MakeMeasureSpec(size, MeasureSpecMode.Exactly); 
     base.OnMeasure(newMeasureSpec, newMeasureSpec); 
    } 
} 

आप एक दृश्य (या किसी अन्य नियंत्रण) वर्ग होना चाहते हैं (और केंद्रित) सिर्फ अपने लेआउट में जोड़ें:

<your.namespace.SquareFrameLayout 
    android:id="@+id/squareContainer" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_gravity="center"> 
    <View 
     android:id="@+id/squareContent" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" /> 
</your.namespace.SquareFrameLayout> 
9

उत्तर देने में देर हो सकती है लेकिन फिर भी, यह नए आगंतुकों के लिए सहायक होगी।

नई ConstraintLayout एंड्रॉयड स्टूडियो 2.3 में शुरू की के साथ

, यह अब काफी संवेदनशील लेआउट का निर्माण करने के लिए आसान है।1 के अनुपात वर्ग लेआउट सुनिश्चित करता है:

एक माता पिता ConstraintLayout में, अपने बच्चों में से किसी को देखना/लेआउट गतिशील वर्ग बनाने के लिए, इस विशेषता

app:layout_constraintDimensionRatio="w,1:1" 

डब्ल्यू चौड़ाई के लिहाज से की कमी और 1 निर्दिष्ट करने के लिए है जोड़ें।

+0

यह एक राजा का जवाब है – itzhar

2

यह रूप में सरल है के रूप में:

public class SquareRelativeLayout extends RelativeLayout { 

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

    public SquareRelativeLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public SquareRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    { 
     if (widthMeasureSpec < heightMeasureSpec) 
      super.onMeasure(widthMeasureSpec, widthMeasureSpec); 
     else 
      super.onMeasure(heightMeasureSpec, heightMeasureSpec); 
    } 
} 
0

चेक बाहर SquareLayout, एक एंड्रॉयड लाइब्रेरी जो, विभिन्न लेआउट के लिए एक आवरण वर्ग प्रदान करता है प्रतिपादन किसी भी कोर कार्यक्षमताओं खोने के बिना उन्हें dimensioned चौकोर।

आयामों की गणना को ले जाने से ठीक पहले की जाती है, इसलिए दृश्य प्राप्त होने के बाद समायोजित करने के लिए कोई पुन: प्रतिपादन या कुछ भी नहीं है।

लाइब्रेरी का उपयोग करने के लिए, अपने build.gradle से जोड़ें:

repositories { 
    maven { 
     url "https://maven.google.com" 
    } 
} 

dependencies { 
    compile 'com.github.kaushikthedeveloper:squarelayout:0.0.3' 
} 

एक आप की आवश्यकता SquareLinearLayout है।