【问题标题】:Custom scrollable layout with default values具有默认值的自定义可滚动布局
【发布时间】:2014-07-11 17:47:10
【问题描述】:

我正在尝试在 ScrollView 中制作自定义 RelativeLayout。
现在我必须将这部分代码复制到我想使用它的每个地方:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="xxx"
        android:layout_height="yyy">

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="top"
            android:layout_margin="@dimen/card_margin"
            android:background="@drawable/card_background"
            android:gravity="center"
            android:padding="@dimen/card_padding">

        // content
    </RelativeLayout>
</ScrollView>

我想用这个得到相同的结果:

<MyScrollableRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="xxx"
        android:layout_height="yyy">

    // content
</MyScrollableRelativeLayout>

这甚至有可能以这种方式实现吗?

更新 1

我尝试过这样:

public class MyScrollableRelativeLayout extends ScrollView {
    private RelativeLayout content;
    int padding;
    int margin;

    public MyScrollableRelativeLayout(Context context) {
        super(context);
        postConstruct();
    }

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

    public MyScrollableRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        postConstruct();
    }

    private void postConstruct() {
        float scale = getResources().getDisplayMetrics().density;
        padding = (int) (5 * scale);
        margin = (int) (20 * scale);

        content = new RelativeLayout(getContext());
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        layoutParams.setMargins(margin, margin, margin, margin);
        addView(content, layoutParams);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        setLook();
    }

    private void setLook() {
        setCardBackground();
        setCardPadding();
    }

    private void setCardBackground() {
        content.setBackground(getResources().getDrawable(R.drawable.card_background));
    }

    private void setCardPadding() {
        setPadding(padding, padding, padding, padding);
    }

    @Override
    public void addView(@NonNull View child) {
        if (getChildCount() == 0) {
            super.addView(child);
        } else {
            content.addView(child);
        }
    }

    @Override
    public void addView(@NonNull View child, int index) {
        if (getChildCount() == 0) {
            super.addView(child, index);
        } else {
            content.addView(child, index);    }
    }

    @Override
    public void addView(@NonNull View child, ViewGroup.LayoutParams params) {
        if (getChildCount() == 0) {
            super.addView(child, params);
        } else {
            content.addView(child, params);
        }
    }

    @Override
    public void addView(@NonNull View child, int index, ViewGroup.LayoutParams params) {
        if (getChildCount() == 0) {
            super.addView(child, index, params);
        } else {
            content.addView(child, index, params);
        }
    }
}

但 ScrollableCardRelativeLayout 中的元素问题正在覆盖自身。就像他们忽略了android:layout_* 属性一样。我做错了什么?

【问题讨论】:

  • 完全可以,如果你遵循这个,developer.android.com/training/custom-views/index.html
  • @petey 你能帮我吗?我在那里找不到我的问题的答案。
  • 问题出在LayoutParams,每次使用params参数调用content.addView时,params取自FrameLayout,而不是RelativeLayout,见generateLayouParams(AttributeSet)

标签: android custom-controls android-custom-view


【解决方案1】:

您可以像这样使用一些棘手的 LayoutParams 包装器:

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;

public class MyScrolledRelativeLayout extends ScrollView {
    private static final String TAG = "MyScrolledRelativeLayout";
    private RelativeLayout rl;

    public MyScrolledRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        rl = new RelativeLayout(context);
        addView(rl);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParamsWrapper(getContext(), attrs);
    }

    public void addView(View child, ViewGroup.LayoutParams params) {
        Log.d(TAG, "addView " + child + " " + params);
        if (getChildCount() != 0) {
            LayoutParamsWrapper layoutParamsWrapper = (LayoutParamsWrapper) params;
            rl.addView(child, layoutParamsWrapper.wrapped);
        }
    };

    class LayoutParamsWrapper extends FrameLayout.LayoutParams {
        private RelativeLayout.LayoutParams wrapped;
        public LayoutParamsWrapper(Context c, AttributeSet attrs) {
            super(c, attrs);
            wrapped = new RelativeLayout.LayoutParams(c, attrs);
        }
    }
}

【讨论】:

  • 真的很棘手。还有一个小问题,设置边距不生效。我想通过android:layout_margin="xx"ScrollableCardRelativeLayout标签中设置它具有相同的效果。
  • 没关系,我的错。我已经将背景添加到 ScrollView 而不是 RelativeLayout 并且想知道为什么它看起来很糟糕,将解决问题。你的回答做的事情,非常感谢你!
猜你喜欢
  • 2011-01-15
  • 2015-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多