मेरे पास यह कंटेनर क्लास है जिसका उपयोग आयामों में से एक बनाने के लिए किया जाता है, या तो चौड़ाई या ऊंचाई, अन्य आयाम का अनुपात। उदाहरण के लिए, मुझे 16: 9 लेआउट कंटेनर चाहिए जहां चौड़ाई "match_parent" है। हालांकि, ऊंचाई को "match_parent" के रूप में उपयोग करते समय, एंड्रॉइड ठीक से खुद को रिलाउट नहीं लग रहा है। जब मैं ऊंचाई को चौड़ाई का अनुपात मानता हूं तो सब कुछ ठीक है! इसके विपरीत और यह काम नहीं करता है। क्या चल रहा है?सापेक्ष लयआउट कस्टम दृश्य की चौड़ाई को सही ढंग से अपडेट नहीं कर रहा है
public class RatioLayout extends ViewGroup {
private float ratio = 1.6222f; // 4 x 3 default. 1.78 is 16 x 9
public float getRatio() { return ratio; }
public void setRatio(float ratio) {
this.ratio = ratio;
requestLayout();
}
public RatioLayout(Context context) {
this(context, null);
}
public RatioLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RatioLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.i("Ratio", "/onMeasure");
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
// int exactly = MeasureSpec.EXACTLY; // 1073741824
// int atMost = MeasureSpec.AT_MOST; // -2147483648
// int unspec = MeasureSpec.UNSPECIFIED; // 0
width = Math.round(height * ratio);
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
int mw = getMeasuredWidth();
int mh = getMeasuredHeight();
Log.i("Ratio", "mw: " + mw + ", mh: " + mh);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.i("Ratio", "/onLayout");
Log.i("Ratio", "l: " + l + ", t: " + t + ", r:" + r + ", b:" + b);
Log.i("Ratio", "mw: " + getMeasuredWidth() + ", mh:" + getMeasuredHeight());
Log.i("Ratio", "w: " + getWidth() + ", mw:" + getHeight());
}
}
कार्रवाई में यह देखने के लिए, इस तरह एक लेआउट का उपयोग करें:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<com.example.RatioLayout
android:id="@+id/image"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginBottom="100dp"
android:layout_marginTop="100dp"
android:background="#FFFF00FF" />
</RelativeLayout>
और ये मेरे गतिविधि होगा:
लॉगिंग उत्पादन:
I/Ratio (9445): /onMeasure
I/Ratio (9445): mw: 1087, mh: 670
I/Ratio (9445): /onMeasure
I/Ratio (9445): mw: 655, mh: 404
I/Ratio (9445): /onLayout
I/Ratio (9445): l: 0, t: 133, r:1087, b:537
I/Ratio (9445): mw: 655, mh:404
I/Ratio (9445): w: 1087, mw:404 <--- NO reason this should not be 655
क्यों Android होगा मेरे नवीनतम मापा Width का सम्मान नहीं करते हैं, लेकिन पुराने संस्करण का उपयोग करते हैं लेकिन नवीनतम ऊंचाई?
संपादित करें: अपडेट किया गया। अनुपात Layout के माता-पिता को रिलेटिवलायआउट बनाएं लेकिन लीनियरलाउट या फ़्रेमलाउट मुझे सही व्यवहार देता है। कुछ कारणों से सापेक्ष लयआउट माइकलविड्थ को "कैशिंग" कर रहा है और सबसे वर्तमान का उपयोग नहीं कर रहा है।
संपादित करें 2: RelativeLayout.onLayout में यह टिप्पणी मेरी जो मेरा मानना है कि एक बग
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// The layout has actually already been performed and the positions
// cached. Apply the cached values to the children.
int count = getChildCount();
// TODO: we need to find another way to implement RelativeLayout
// This implementation cannot handle every case
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
अंतिम संपादन ठीक है कि "यह कैशिंग है" पुष्टि करने के लिए लगता है। मैं हार मानता हूं। यह RelativeLayout में एक कानूनी बग है। इस कोड को एक तरह से यह ठीक करता है, लेकिन यह toRightOf गुणों के साथ मुद्दों पैदा करता है। मैंने जो काम पाया वह इस अनुपात को घूमने के लिए लाइनरलाउट जैसे किसी अन्य व्यू ग्रुप में घूमना था। उन उत्सुक
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.i("Ratio", "/onMeasure");
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
// int exactly = MeasureSpec.EXACTLY; // 1073741824
// int atMost = MeasureSpec.AT_MOST; // -2147483648
// int unspec = MeasureSpec.UNSPECIFIED; // 0
width = Math.round(height * ratio);
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
if (getParent() instanceof RelativeLayout) {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)getLayoutParams();
Class<?> clazz = RelativeLayout.LayoutParams.class;
try {
Field left = clazz.getDeclaredField("mLeft");
Field right = clazz.getDeclaredField("mRight");
left.setAccessible(true);
right.setAccessible(true);
int l = left.getInt(params);
if (l == -1) l = params.leftMargin; // if the value is uninitialized, set it to 0;
if (l == -1) l = 0; // if the value is uninitialized, set it to 0;
// setting this seems to break the layout_marginLeft properties.
right.setInt(params, l + getMeasuredWidth());
} catch (NoSuchFieldException e) {
Log.e("Ration", "error", e);
} catch (IllegalArgumentException e) {
Log.e("Ration", "error", e);
} catch (IllegalAccessException e) {
Log.e("Ration", "error", e);
}
}
int mw = getMeasuredWidth();
int mh = getMeasuredHeight();
lastWidth = mw;
Log.i("Ratio", "mw: " + mw + ", mh: " + mh);
}