【问题标题】:Custom View Buttons自定义视图按钮
【发布时间】:2012-06-10 02:46:07
【问题描述】:

我这里有一个自定义视图,然后我想要一些小部件来配合它。

<com.zone.manager.Tab3
    android:id="@+id/tab3_display"
    android:layout_width="fill_parent"
    android:layout_height="620dp" >

<Button
    android:id="@+id/addZone"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Add Zone" />

</com.zone.manager.Tab3>

现在我想将该按钮设置为 onclicklistener,这样我就可以在 View 类中使用它做一些事情,所以我这样做了...

addZone = (Button) findViewById(R.id.addZone);


  addZone.setOnClickListener(this);

我在

public class Tab3 extends ViewGroup implements OnTouchListener, OnClickListener
    Public Tab3(Context context, AttributeSet attrs) 
    {
    super (context, attrs); 
    // here
    }

当我扩展 ViewGroup 时,它让我实现了这个

@Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) 
    {
        // TODO Auto-generated method stub

    }

为了完成这项工作,我应该在此处放入一些东西吗?

但是当我尝试运行应用程序时它崩溃了,但是如果我 // 退出 addZone.setOnClickListener(this); 应用程序运行正常,对我有什么帮助吗?

标签

        th.setup();
        TabSpec specs = th.newTabSpec("tag0");
        specs.setContent(R.id.connecttionTab);
        specs.setIndicator("Connection Tab");
        th.addTab(specs);
        specs = th.newTabSpec("tag1");
        specs.setContent(R.id.tab1);
        specs.setIndicator("Zone Manager");
        th.addTab(specs);
        specs = th.newTabSpec("tag2");
        specs.setContent(R.id.tab2);
        specs.setIndicator("",res.getDrawable(R.drawable.ic_tab_vaccontrol));
        th.addTab(specs);
        //this is the tab that has all this vvv
        specs = th.newTabSpec("tag3");
        specs.setContent(R.id.tab3);
        specs.setIndicator("Graphical Layout");
        th.addTab(specs);

【问题讨论】:

  • 当您更改为 ViewGroup 时,您是否也更改了 xml 以使 Button 是嵌套在 Tab3 元素内的子元素?如果它只是像您发布的 xml 一样跟随它,findViewById 仍然找不到它。而且,是的,您需要实现 onLayout 来决定每个子元素(在本例中,只是 Button)应放置在父 Tab3 元素的边界内的位置。
  • 对不起,我不明白这是什么意思。你能给我解释一下吗?
  • 在我的回答中查看我的第一个示例 xml 代码。请注意,第一个标签 not 结束 Tab3 元素。 (它以&gt; 而不是/&gt; 结尾,并且有一个&lt;/com.zone.manager.Tag3&gt; 标签 Button 标签之后。)Button 元素是Tab3.
  • 我建议您使用我建议的第二种布局方法。我不知道您到底想要什么布局,所以我无法提供具体的布局供您尝试。你能解释一下屏幕上的布局应该是什么(即 Tab3 应该显示在哪里以及按钮应该显示在哪里)?如果按钮应该在 Tab3 的顶部,那么您也许可以使用 RelativeLayout 或 FrameLayout 来获得良好的效果。
  • 该按钮应该位于 Tab3 下方,您能否编辑您的答案以向我展示我想要做什么,因为我很困惑。

标签: android class view android-widget


【解决方案1】:

在您的 xml 中,您的自定义视图不包含按钮;这是一个兄弟视图。您的应用程序崩溃的原因是findViewById(R.id.addZone) 正在返回null,因此当您调用addZone.setOnClickListener(this) 时您会得到NullPointerException。如果您希望自定义视图包含按钮,则​​ xml 必须如下所示:

<com.zone.manager.Tab3
    android:id="@+id/tab3_display"
    android:layout_width="fill_parent"
    android:layout_height="620dp" >

    <Button
        android:id="@+id/addZone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Add Zone" />

</com.zone.manager.Tab3>

此外,您的 Tab3 类必须扩展 ViewGroup,而不是 View。这可能会有点复杂,因为您还需要编写代码来进行布局。该按钮也将显示在Tab3 视图中。

编辑

根据您尝试执行的操作,我不推荐上述方法。相反,您应该将自定义视图和 Button 包装在 LinearLayout 中。例如,以下布局会将按钮放在屏幕的左下角,并且将有一个 Tab3 视图填充其上方的区域:

res/layout.tab3.xml

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <com.zone.manager.Tab3
        android:id="@+id/tab3_display"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <Button
        android:id="@+id/addZone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onAddZone"
        android:text="Add Zone" />

</LinearLayout>

然后,将点击处理逻辑移至Tab3 中的一个单独方法,该方法对您的Activity 类可见。 (假设它被称为addZone()。)Tab3 类不应该实现OnClickListener,而应该扩展View(不是上面的ViewGroup)。通过向按钮添加android:onClick 属性,您无需向按钮添加OnClickListener。相反,您需要在活动中实现该名称的点击方法:

private Tab3 mTab3;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.tab3);
    mTab3 = (Tab3) findViewById(R.id.tab3_display);
    // . . .
}

@Override
/**
 * Called when a view with attribute android:onClick="onAddZone"
 * is clicked.
 *
 * @param view the view that was clicked.
 */
public void onAddZone(View view) {
    mTab3.addZone();
}

虽然您的代码中没有关于按钮的任何内容,但框架会使用反射自动连接所有内容,以便在单击按钮时调用活动的 onAddZone 方法。

【讨论】:

  • 我更新了我的问题,我按照你说的做了,但是如果我有 addZone.setOnClickListener 并且如果我没有在我的绘制部分中没有它,它仍然会崩溃?有什么想法吗?
  • @MichaelZeuner - 我根据您的更新和 cmets 更新了我的答案。
  • 当我点击按钮时,应用程序崩溃了。
  • 我收到一条错误消息,提示 java.lang.IllegalStateException:在视图类 android.widget 上的 onClick 处理程序的活动类 com.zone.manager.VacControl 中找不到方法 onAddZone(View)。 ID 为“addZone”的按钮
  • @MichaelZeuner - 好吧,你有没有按照我说的在你的活动类中添加这样的方法?
【解决方案2】:

在 xml 文件中具有布局时,这不是扩展视图组的正确方法。您需要将您的 xml 更改为如下所示:

R.layout.xml_file_for_custom_view

<merge xmlns:android="http://schemas.android.com/apk/res/android" 
       xmlns:tools="http://schemas.android.com/tools"

       tools:parentTag="com.zone.manager.Tab3">

    <Button
        android:id="@+id/addZone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Add Zone" />

</merge>

在您的自定义视图代码中,您需要扩充 xml 并添加您的 onclick 侦听器:

Tab3.java

public class Tab3 extends ViewGroup implements OnTouchListener, OnClickListener
    
    public Tab3(Context context, AttributeSet attrs) {
        super (context, attrs);
        // inflate and attach the layout to this viewgroup
        View.inflate(getContext(), R.layout.xml_file_for_custom_view, this);
    }

    @Override
    public void onFinishInflate() {
        super.onFinishInflate();
        // Now you can find the button
        addZone = (Button) findViewById(R.id.addZone);
        addZone.setOnClickListener(this);
    }
}

现在,无论您在何处使用自定义视图,您都可以:

<com.zone.manager.Tab3
    android:id="@+id/tab3_display"
    android:layout_width="fill_parent"
    android:layout_height="620dp"/>

关于onLayout方法的问题:

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    // TODO Auto-generated method stub
}

是的,您需要在其中放置一些代码。请参阅 this guide 以帮助您入门。

【讨论】:

    猜你喜欢
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-20
    相关资源
    最近更新 更多