【问题标题】:Android: How to make a Button Lead to a ListView item details (In differents Activities) (Master / Detail Flow)Android:如何使按钮导致 ListView 项目详细信息(在不同的活动中)(主/详细信息流)
【发布时间】:2016-03-05 12:02:43
【问题描述】:

我是 Android 开发的初学者。
我知道,这个标题似乎很难理解,但请让我解释一下

我的应用是我所在城市的公交线路指南,它包含两个不同的视图:

  • 一个ListView,所有公交线路都是数字的,简单的顺序,什么都没有 特别的。它包含正好 100 个项目。
  • NavigationDrawer 的另一项活动使用这些相同的线,但由区域(北、南、东、东南)隔开

每个NavigationDrawer 菜单都指向一个带有多个按钮和总线线路的活动,但仅限于属于 X 区(例如东区)的活动

这里是ActivityEast的布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="6dp"
    android:paddingBottom="6dp"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_leste" tools:context="com.lennoardsilva.teresinabus.Leste">

    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/scrollView2"
        android:layout_alignParentTop="true">

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

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_245"
                android:id="@+id/botao_l_245" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_401"
                android:id="@+id/botao_l_401" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_402"
                android:id="@+id/botao_l_402" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_403"
                android:id="@+id/botao_l_403" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_404"
                android:id="@+id/botao_l_404" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_405"
                android:id="@+id/botao_l_405" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_501"
                android:id="@+id/botao_l_501" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_502"
                android:id="@+id/botao_l_502" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_503"
                android:id="@+id/botao_l_503" />
            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_512"
                android:id="@+id/botao_l_512" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_513"
                android:id="@+id/botao_l_513" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_518"
                android:id="@+id/botao_l_518" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_520"
                android:id="@+id/botao_l_520" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_521"
                android:id="@+id/botao_l_521" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_522"
                android:id="@+id/botao_l_522" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_523"
                android:id="@+id/botao_l_523" />

            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/l_610"
                android:id="@+id/botao_l_610" />
            <Button
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/carregar_mais"
                android:id="@+id/botao_carregar_leste"
                android:background="@color/cinza_escuro"
                android:textColor="@color/branco"
                android:textStyle="bold"
                android:onClick="leste_2"
                android:visibility="gone" />

        </LinearLayout>
    </ScrollView>
</RelativeLayout>

<!-- As a told you, a lot of buttons -->

这里是 LineListFragment:

package com.lennoardsilva.teresinabus;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.lennoardsilva.teresinabus.dummy.DummyContent;

public class LinhaListFragment extends ListFragment {

    private static final String STATE_ACTIVATED_POSITION = "activated_position";

    private Callbacks mCallbacks = sDummyCallbacks;

    private int mActivatedPosition = ListView.INVALID_POSITION;

    public interface Callbacks {
        public void onItemSelected(String id);
    }

    private static Callbacks sDummyCallbacks = new Callbacks() {
        @Override
        public void onItemSelected(String id) {
        }
    };

    public LinhaListFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setListAdapter(new ArrayAdapter<DummyContent.DummyItem>(getActivity(),android.R.layout.simple_list_item_activated_1, android.R.id.text1, DummyContent.ITEMS));
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (savedInstanceState != null && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
            setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
        }
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        // Activities containing this fragment must implement its callbacks.
        if (!(activity instanceof Callbacks)) {
            throw new IllegalStateException("Activity must implement fragment's callbacks.");
        }
        mCallbacks = (Callbacks) activity;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mCallbacks = sDummyCallbacks;
    }

    @Override
    public void onListItemClick(ListView listView, View view, int position, long id) {
        super.onListItemClick(listView, view, position, id);

        mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (mActivatedPosition != ListView.INVALID_POSITION) {
            outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
        }
    }

    public void setActivateOnItemClick(boolean activateOnItemClick) {
        getListView().setChoiceMode(activateOnItemClick ? ListView.CHOICE_MODE_SINGLE : ListView.CHOICE_MODE_NONE);
    }

    private void setActivatedPosition(int position) {
        if (position == ListView.INVALID_POSITION) {
            getListView().setItemChecked(mActivatedPosition, false);
        } else {
            getListView().setItemChecked(position, true);
        }
        mActivatedPosition = position;
    }
}

这里是行ListActivity:

public class LinhaListActivity extends AppCompatActivity
        implements LinhaListFragment.Callbacks {

    private boolean mTwoPane;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_linha_app_bar);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        toolbar.setTitle(getTitle());

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                DialogFragment dialog = new FragmentoDatabase();
                dialog.show(getFragmentManager(), "FragmentoDatabaseTag");

            }
        });
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        if (findViewById(R.id.linha_detail_container) != null) {
            mTwoPane = true;
            ((LinhaListFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.linha_list))
                    .setActivateOnItemClick(true);
        }

        // TODO: If exposing deep links into your app, handle intents here.
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == android.R.id.home) {
            NavUtils.navigateUpFromSameTask(this);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onItemSelected(String id) {
        if (mTwoPane) {
            Bundle arguments = new Bundle();
            arguments.putString(LinhaDetailFragment.ARG_ITEM_ID, id);
            LinhaDetailFragment fragment = new LinhaDetailFragment();
            fragment.setArguments(arguments);
            getSupportFragmentManager().beginTransaction().replace(R.id.linha_detail_container, fragment).commit();

        } else {
            Intent detailIntent = new Intent(this, LinhaDetailActivity.class);
            detailIntent.putExtra(LinhaDetailFragment.ARG_ITEM_ID, id);
            startActivity(detailIntent);
        }
    }
}

这里是虚拟内容:

public class DummyContent {

    public static List<DummyItem> ITEMS = new ArrayList<DummyItem>();

    public static Map<String, DummyItem> ITEM_MAP = new HashMap<String, DummyItem>();

    static {
        addItem(new DummyItem("1", "004 - LINE NAME", "Line 004 Details"));
        addItem(new DummyItem("2", "005 - LINE NAME", "Line 005 Details"));
        addItem(new DummyItem("3", "And so on....", "Details"));
        addItem(new DummyItem("100", "100 - LINE NAME", "Line 100 Details"));
      }

    private static void addItem(DummyItem item) {
        ITEMS.add(item);
        ITEM_MAP.put(item.id, item);
    }
    public static class DummyItem {
        public String id;
        public String content;
        public String details;

        public DummyItem(String id, String content, String details) {
            this.id = id;
            this.content = content;
            this.details = details;
        }

        @Override
        public String toString() {
            return content;
        }
    }
}

问题:如何让其中一个按钮启动ListView对应的ItemDetailsActivity?

示例:在 ActivityEast 我有 botao_l_501,在 ListView 它对应于 item 33。 我希望 botao_l_501 开始ListView 的第 33 项的详细信息。 (模板主/详细信息流,谷歌)

您可能想知道的事情:

  • ListView 位于另一个 Activity 中,与中的所有项目分开 Navigation Drawer,但您可以通过 FAB 启动它;
  • ListView 是主/明细流的模型。项目是 已设置(尚未详细说明);

【问题讨论】:

    标签: android listview button android-button


    【解决方案1】:

    所以基本上你需要与区域活动(即ActivityEast)共享LinhaListFragment 中的适配器信息。问题是在LinhaListFragment 你有一个Adapter 因为你使用的是ListFragment 但在ActivityEast 你有一个LinearLayout 和一堆Buttons,所以我们如何映射这两件事要一起工作吗?

    第一个解决方案(Hack & Nasty)

    在您的 DummyContent 类中,当您添加项目时,还要添加对 Button id 的引用:

    static {
        addItem(new DummyItem(R.id.idbotao_l_001, "1", "004 - LINE NAME", "Line 004 Details"));
        addItem(new DummyItem(R.id.idbotao_l_002, "2", "005 - LINE NAME", "Line 005 Details"));
        addItem(new DummyItem(R.id.idbotao_l_033, "33", "033 - LINE NAME", "Details"));
        addItem(new DummyItem(R.id.idbotao_l_100, "100", "100 - LINE NAME", "Line 100 Details"));
      }
    

    然后在每个按钮的 onClick 中,您可以执行以下操作:

    @Override
    public void onClick(View view) {
        for (DummyItem item : DummyContents.ITEMS) {
             if (item.resourceId == view.getId()) {
                 //Start the item detail activity
                 break;
             }
        }
    }
    

    我不知道您是否使用DummyContent 类,因为如果您使用它,您的内容永远不会改变,因为您只是在测试代码。如果将来您要从 Web 服务中获取该数据,那么此解决方案将毫无用处。

    第二种解决方案(清洁)

    首先,如果您真的想遵循主/详细规范,那么您应该仅将活动用作片段持有者,因此像 ActivityEast 这样的区域活动不应该存在,您也不应该有一个 LinearLayout 和一堆按钮。将其替换为包含ZoneFragmentRecyclerViewZoneActivity(不再使用ListViewListFragmentRecyclerView 应设置为与您在@987654343 中使用的Adapter 相同的Adapter @当您启动ZoneActivity时,要求区域ID由Intent的捆绑包发送,该ID通过ZoneFragment并最终设置为AdapterAdapter 包含过滤/显示每个区域的行的逻辑。 zone id 参数应该不是必需的,因为 ListFragment 它也将使用相同的适配器并且没有 zone id。

    既然您说您刚刚开始从事 android 开发,那么有一些技巧可以帮助您:

    • 不要使用ListView,而是使用RecyclerView

    • 永远不要像在 ActivityEast 中所做的那样,如果您将有这么多按钮使用 RecyclerView,即使您的数据是静态的。

    • 没有人再使用像ListFragment 这样的东西了。如果您从您附加到该类的类似内容扩展,请尝试从您自己的基类或非常基本的基类(如 Fragment 和 Activity)继承。

    • 尝试使用区域而不分离您的代码。例如:

    公共类 MyFragment 扩展片段 {

    //region Variables
    private int myField;
    //endregion
    
    //region Fragment lifecycle
    protected void onCreate(Bundle saveInstance) {
     //...
    }
    //endregion
    }
    

    然后您可以将它们折叠起来,以更舒适的方式阅读代码。

    • 永远不要明确启动活动,例如:

    不好

    Intent intent = new Intent(context, MyActivity.class);
    intent.putExtra("zoneId",myZoneId);
    startActivity(intent);
    

    startActivity(MyActivity.getStartIntent(context, myZoneId));
    
    ....
    //In MyActivity class
    public static getStartIntent(Context context, int zoneId) {
        Intent intent = new Intent(context, MyActivity.class);
        intent.putExtra(MyActiviy.ZONE_ID, zoneId);
        return zoneId;
    }
    

    }

    【讨论】:

    • 感谢您的帮助!!!!有很多内容,所以我现在就开始搜索。对我来说仍然有点困难,但我不会放弃。关于那个按钮,这是我发现的第一个简单的解决方案,现在我知道我应该做什么。提前致谢。正如你所说,第二个解决方案看起来很干净,我会试试
    • 很高兴这个答案对您有所帮助,如果您对答案感到满意,请接受。
    • 好吧,tzz 它真的帮了很多忙,如果你能解释一下,呃... Noob 友好的第二个...我会很高兴的。
    • 是的,别担心,给我几分钟,我会更新答案。
    • 请不要担心,我已经转到 RecyclerView。我做了一个非常漂亮的列表,但现在我遇到了 OnClickListener 的问题,我无法为每张卡单独设置它。 Stack Overflow 都没有帮助我......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多