java - 如何在 Robolectric 中为自定义 View 配置 RoboAttributeSet?

标签 java android xml attr robolectric

我正在使用我自己的属性测试一个(有效的)复合控件(又名自定义 View ),并尝试使用 RoboAttributeSet 来配置 View 的属性。我还没有找到有关此功能的综合示例或文档,以及在使用构造函数时我的属性创建要使用哪些值。我确信它很容易修复,但我还没找到它。

我已经复习了这些问题:RoboAttributeSet , Custom view inflation error , 和 Shadowing custom views ...和互联网的其余部分无济于事。

注意:我的完整包名称是:com.colabug.local.food

注意:我使用的文件名不是 Android 教程中描述的 attrs.xml

CoverViewTest.java

public class CoverViewTest
{
    private Activity activity;
    private CoverView coverView;

    // Data
    private Delicacy data;

    // UI
    private RatingBar ratingBar;

    @Before
    public void setUp() throws Exception
    {
        activity = createActivity();
        coverView = getCoverView( activity, null );
        data = createDummyData( false, 2, false );
        coverView.setData( data );

        ratingBar = (RatingBar) coverView.findViewById( R.id.cover_view_rating_bar );
    }

    private CoverView getCoverView( Activity activity,
                                    RoboAttributeSet attributeSet )
    {
        CoverView view;
        view = new CoverView(Robolectric.application.getApplicationContext(), attributeSet);

//        view = (CoverView) LayoutInflater.from( activity )
//                                         .inflate( R.layout.cover_view,
//                                                   new CoverView( activity ),
//                                                   true );

        return view;
    }

    @Test
    public void showRatingBarAttribute_shouldShowRatingBar() throws Exception
    {
        ArrayList<Attribute> attributes = new ArrayList<Attribute>();
        attributes.add( new Attribute( "com.colabug.local.food:cover_attrs/showRatingBar", String.valueOf( true ), "com.colabug.local.food") );
        RoboAttributeSet attributeSet = new RoboAttributeSet( attributes,
                                                              Robolectric.application.getResources(),
                                                              CoverView.class );

        CoverView view = getCoverView( activity, attributeSet );
        view.setData( createDummyData( false, 2, false ) );
        assertViewIsVisible( view.findViewById( R.id.cover_view_rating_bar ) );
    }
}

错误

java.lang.IllegalStateException: "com.colabug.local.food:cover_attrs/showRatingBar" unexpected
    at org.robolectric.res.Attribute.<init>(Attribute.java:90)
    at org.robolectric.res.Attribute.<init>(Attribute.java:86)
    at com.colabug.local.food.views.CoverViewTest.setShowRatingBar_shouldShowRatingBar(CoverViewTest.java:140)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:250)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:177)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:24)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:77)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

res/values/cover_attrs.xml

<?xml version="1.0" encoding="utf-8"?>

<resources>
   <declare-styleable name="CoverView">
       <attr name="showRatingBar" format="boolean" />
   </declare-styleable>
</resources>

CoverView.java

public class CoverView extends RelativeLayout
{
    private BaseModel data;

    // UI
    private LayoutInflater inflater;
    private RatingBar      ratingBar;

    // Attributes
    private boolean showRatingBar = false;

    public CoverView( Context context )
    {
        super( context );
        inflater = LayoutInflater.from( context );
        initViews();
    }

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

        getStyledAttributes( context, attrs );
        inflater = LayoutInflater.from( context );
        initViews();
    }

    public CoverView( Context context, AttributeSet attrs, int defStyle )
    {
        super( context, attrs, defStyle );

        getStyledAttributes( context, attrs );
        inflater = LayoutInflater.from( context );
        initViews();
    }

    public static CoverView inflate( ViewGroup parent, int layoutId )
    {
        return (CoverView) LayoutInflater.from( parent.getContext() )
                                         .inflate( layoutId, parent, false );
    }

    private void initViews()
    {
        inflater.inflate( R.layout.cover_view, this );
        ratingBar = (RatingBar) findViewById( R.id.cover_view_rating_bar );
    }

    private void getStyledAttributes( Context context, AttributeSet attrs )
    {
        TypedArray attributes = getAttributeArray( context, attrs );

        try
        {
            showRatingBar = attributes.getBoolean( R.styleable.CoverView_showRatingBar, false );
        }
        finally
        {
            attributes.recycle();
        }
    }

    private TypedArray getAttributeArray( Context context, AttributeSet attrs )
    {
        return context.getTheme().obtainStyledAttributes( attrs, R.styleable.CoverView, 0, 0 );
    }

    public void setData( BaseModel data )
    {
        this.data = data;

        configureRatingBar();

        redrawView();
    }

    private void redrawView()
    {
        invalidate();
        requestLayout();
    }

    private void configureRatingBar()
    {
        if ( showRatingBar )
        {
            ratingBar.setVisibility( VISIBLE );
        }
        else
        {
            ratingBar.setVisibility( GONE );
        }
    }

    public boolean hasRatingBar()
    {
        return showRatingBar;
    }

    public void setShowRatingBar( boolean showRatingBar )
    {
        this.showRatingBar = showRatingBar;
        redrawView();
    }
}

res/layout/cover_view.xml

<merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/MatchWidth">

    <!--Location image-->
    <ImageView
        android:id="@+id/cover_view_image"
        android:adjustViewBounds="true"
        android:src="@drawable/philly"
        android:contentDescription="@string/LOCATION_CONTENT_DESC"
        style="@style/MatchWidth"/>

...    

        <!--Rating bar-->
        <RatingBar
            android:id="@+id/cover_view_rating_bar"
            style="@style/RatingBar"/>
</merge>

最佳答案

对于那些仍然想知道如何在版本 3 中进行配置的用户:查看 Roboelectric 的示例。我花了很长时间才找到这个。

https://github.com/robolectric/robolectric/blob/490e5fcb7165bec9ef2ddc1c937af790806bb13d/robolectric/src/test/java/org/robolectric/shadows/ViewStubTest.java#L59

关于java - 如何在 Robolectric 中为自定义 View 配置 RoboAttributeSet?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24999471/

相关文章:

android - 赠送或测试付费 Android 应用程序

javascript - 如何通过 jquery/JavaScript 使用 Google XML 建议

Python Grequests xml 响应

java - 使用 TelephonyManager 获取 SIM 国家代码 - 如何?

java - 套接字无法在网络中工作

java - 更改 Java 中的键盘输入语言

java - 如何强制 max 返回 Java Stream 中的所有最大值?

android - 如何更改终端的默认目录?

android - flutter + firebase + Stripe

javascript - 使用 Javascript 解析 XML 对象数组中的数据