Android:何时在父视图大小更改时调用影响子布局的方法?

时间:2014-01-29 23:26:03

标签: android android-layout resize

我有一个非常简单的RelativeLayout子类,它添加了一个带有文本视图的图像视图。我有一个方法show(),它创建并添加子视图并设置初始文本。

在我第一次调用show()时,视图不知道它有多大,所以我不能为textView设置textSize和填充。

我有一个主要有效的解决方案,我在重写方法onSizeChanged()中为textView调用setTextSize()和setPadding()。文本第一次显示时不显示。然而,它在每次之后显示,尺寸和放置都很完美。

以下是onSizeChanged()的代码:

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    Log.e(TAG, "onSizeChanged() called");
    if (_childTextView != null) {
        float textSize   = h / 2.0f;
        int   topPadding = (int)(h / 3.0f);
        Log.e(TAG, "setting textSize = " + textSize);
        Log.e(TAG, "topPadding = " + topPadding);
        _childTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
        _childTextView.setPadding(0, topPadding, 0, 0);
    }
    super.onSizeChanged(w, h, oldw, oldh);
    Log.e(TAG, "end onSizeChanged()");
}

show()的代码如下:

public void show(int val) {
    _val = val;

    Log.e(TAG, "in show(), val = " + val);

    // create and add background image if not already there
    if (_backgroundImageView == null) {
        _backgroundImageView = new ImageView(_context);
        _backgroundImageView.setImageResource(R.drawable.background);

        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        params.addRule(CENTER_IN_PARENT);
        addView(_backgroundImageView, params);
    }

    // create and add text view if not already there
if (_childTextView == null) {
        _childTextView = new TextView(_context);
        _childTextView.setTextColor(Color.BLACK);

        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

        params.addRule(CENTER_HORIZONTAL);
        addView(_childTextView, params);
    }
    Log.e(TAG, "setting text to: " + _val);

// update value and make visible
    _childTextView.setText(String.valueOf(_val));
    setVisibility(VISIBLE);
    Log.e(TAG, "end show()");
}

每次都能正确显示背景图像。 textView仅在第二次调用show()时才会正确显示。登录onSizeChanged()会显示第一次计算的数字是正确的。正如预期的那样,onSizeChanged()在我们从show()返回后第一次被调用。对show()的后续调用只是设置值和可见性,文本显示正确。

我的问题是:有更好的方法吗?还是一个更好的回调方法来覆盖?

尝试在show()中设置这些值不起作用,因为主视图还不知道自己的大小(至少第一次)。我试过在onSizeChanged()的末尾添加invalidate()。我也尝试过调用setText()。

我需要能够根据大小来做这件事,因为这个类在图像需要更小或更大的不同环境中重复使用。

感谢您提供的任何见解。如果可能的话,我真的很想保持这个。

编辑:我要做的是将一些文本的大小设置为子图像大小的1/2(与父级大小相同),并将顶部填充设置为约1/3图像大小。如果我只是希望它是一个尺寸,那将很容易。但是,我希望它可以根据显示器的需要进行尺寸调整。

想象一下邮票,你想把价值放在图像中的某个地方。到现在为止还挺好。但是如果这张邮票需要在同一部手机上以不同尺寸显示呢?您需要相应地调整放置偏移(填充)和文本大小。如果我将其硬编码到xml中,那么在调整布局大小时,不会调整文本大小和位置。小版本的文字太大,而且距离图像顶部太远。

1 个答案:

答案 0 :(得分:-1)

我不知道为什么你重写onSizeChanged(),如果你按照它的意图使用它,那么正常的android会很好地处理这一切。 你可以解释一下你想要实现的目标吗 - 也许用例子图片?

但是我想知道当你覆盖其余部分时你不会覆盖onMesure(),如果对show()的延迟调用有帮助,也可能是因为onMesure被调用。

编辑:

    在Android中你应该永远不想知道一些视图的真实大小。几乎每个设备都有其他尺寸,也有纵向/横向模式。如果您开始编码与实际尺寸,您可以在开始时放弃。相反,你应该使用更像 dp sp 的东西,而不是再次担心文字大小和类似内容。
  • 您可能还需要,并且应尽可能在应用程序中使用LayoutInflaterxml个文件。在Activity中,您可以拨打setContentView()。在其他情况下,可能有像onCreateView这样的重载方法。如果你没有别的,你可以这样做:

    LayoutInflater inflater = LayoutInflater.from(contextEgActivity);
    View rootView = inflater.inflate(R.layout.highscore_daily, parentCanBeNull);
    

编辑II: 所以这就是你想要的 - 对吧? (在ImageView和TextView上,使用wrap_content进行高度和宽度会更好)

<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:id="@+id/imageView"
    android:layout_gravity="center"
    android:background="#ff0000" />
<TextView
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:text="New Text"
    android:id="@+id/textView"
    android:layout_gravity="center"
    android:background="#00ff00"
    android:textSize="20sp" />
</FrameLayout>

如果你只有3种不同的尺寸我会写3个不同的xml文件来匹配你想要的。否则我认为这段代码符合您的需求。

//http://stackoverflow.com/questions/4605527/converting-pixels-to-dp
public static float convertDpToPixel(float dp, Context context){
    Resources resources = context.getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return px;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);//loads the xml above

    ImageView v = (ImageView) findViewById(R.id.imageView);
    int dp = 200;
    int px = (int) convertDpToPixel(dp, this);
    v.setMaxHeight(px);//no need for it
    v.setMinimumHeight(px);//should do more or less the same as next line
    v.setLayoutParams(new LinearLayout.LayoutParams(px, px));//is like android:layout_width="200dp" android:layout_height="200dp"
    v.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, px));//is like android:layout_width="wrap_content" android:layout_height="200dp"
    //basically you can do the same with the TextView + the Text styling
    TextView tv = (TextView) findViewById(R.id.textView);
    tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 50);
    tv.setPadding(30,30,30,30);//don't forget, this is also px so you may need dp to px conversion
}
这是正常的方式,干净又简单。如果你为什么还想对你父母的尺寸变化作出反应,你可以尝试这个,但我不建议。 btw更改视图的东西应该只能从ui / main线程执行,所以如果从Handler new Handler(getMainLooper)之类的其他线程调用该方法,那么{{1}}