RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 647662
Accepted
RareScrap
RareScrap
Asked:2020-04-03 15:13:36 +0000 UTC2020-04-03 15:13:36 +0000 UTC 2020-04-03 15:13:36 +0000 UTC

更改片段的标记而不重新创建它

  • 772

我想这样做,以便我的片段可以更改其标记而无需重新创建自身(即无需重新创建片段并调用其构造函数)。我试过使用 ViewGroup 及其 setView() 和 removeView() 方法将一个标记替换为另一个标记,但我似乎变得更加困惑。

还有另一种方法可以解决我的问题 - 在 Activity 标记中,立即为每个标记创建两个片段,使其中一个不可见。我认为从效率和节省资源的角度来看,这不是一种有效和正确的方法。我想知道您对如何最好地解决这个问题的看法。

下面您可以看到一段代码解决了我的问题,但是重新创建了片段对象并在单击操作栏上的特定按钮之后。当您需要更改片段的标记而不重新创建它时该怎么办?

// Обработка выбора команд меню
@Override
public boolean onOptionsItemSelected(android.view.MenuItem item) {
    FragmentManager fm = getFragmentManager(); // Необходим для транзакий фрагментов: при удалении и заменене одного фрагмента другим

    // Выбор в зависимости от идентификатора MenuItem
    switch (item.getItemId()) {
        case R.id.shopping_cart:
            return true; // Событие меню обработано
        case R.id.sort:
            if (fm != null) {
                /*
                Perform the FragmentTransaction to load in the list tab content.
                Using FragmentTransaction#replace will destroy any Fragments
                currently inside R.id.fragment_content and add the new Fragment
                in its place. (с) Google doc
                */
                FragmentTransaction ft = fm.beginTransaction(); // Начало транзакции
                ( (ViewGroup) getActivity().findViewById(R.id.fragment_menu) ).removeAllViews(); // Удаляет View на экране (сам список)
                ft.remove(this); // Удаляет кнопки на палени действий (TODO: и вместе с ним сам фрагмент?)

                // Замена фрагмента
                if (currentMode == CARD_MODE) {
                    ft.replace(R.id.fragment_menu, new MenuListFragment().setArguments(PLATE_MODE));
                }else {// currentMode == PLATE_MODE
                    ft.replace(R.id.fragment_menu, new MenuListFragment().setArguments(CARD_MODE));

                }
                ft.commit(); // Завершение транзакции
            }
            return true; // Событие меню обработано
    }

    return super.onOptionsItemSelected(item); //TODO: Разобраться зачем вообще тут нужен супер
}

如果您需要其余代码和标记,这里是完整项目代码的链接:https ://github.com/RareScrap/TennoSushi/tree/master

更新 1这是两个标记的代码,将代码显示为图块和普通列表

fragment_menu_card_list.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/card_main"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context="com.webtrust.tennosushi.MenuListFragment">

     <!-- TODO: Update blank fragment layout -->

     <ListView
          android:id="@+id/cardList"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="horizontal"></ListView>
</FrameLayout>

fragment_menu_plates_list.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/plates_main"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context=".MainActivity">

     <GridView
          android:id="@+id/platesList"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:horizontalSpacing="0dp"
          android:numColumns="2"
          android:verticalSpacing="0sp" />

</RelativeLayout>

更新 2片段代码

package com.webtrust.tennosushi;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import android.widget.ListView;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * Простой наследник класса {@link Fragment}.
 * Активити, которые содержат этот фрагмент должно реализовывать
 * интерфейс {@link MenuListFragment.OnFragmentInteractionListener}
 * для обработки событий взаимодействия между активностью и фрагментом.
 * Используйте {@link MenuListFragment#newInstance} фабричный метод для
 * создания экземпляра этого фрагмента.
 * @author RareScrap
 */
public class MenuListFragment extends Fragment {
     // Константы, определяющие режим отображения списка
     public static int CARD_MODE = 0;
     public static int PLATE_MODE = 1;

     // Закомментирован, т.к. еще не изучен
     //private OnFragmentInteractionListener mListener;

     // Список объектов MenuItem, представляющих элементы главного меню (категории блюд)
     private List<MenuItem> menuItemList = new ArrayList<>();

     // ArrayAdapter связывает объекты MenuItem с элементами ListView
     private MenuItemArrayAdapter menuItemArrayAdapter;
     private ListView menuItemListListView; // View для вывода информации в виде списка
     private GridView menuItemListGridView; // View для вывода информации в виде плиток

     private int currentMode; // Текущий режим отображения списка

     /**
      * Необходимый пустой публичный конструктор
      */
     public MenuListFragment() {
          setArguments(PLATE_MODE);// режим по умолчанию
     }

     /**
      * Метод-замена для конструктора с параметрами т.к.
      * Google ОЧЕНЬ не рекомендует иметь дополнительные конструкторы
      * во фрагментах
      *
      * @param mode Режим отображения списка
      * @return this Возвращает этот же фрагмент (нужночтобы вызывать сразу после конструктора во FragmentTransaction
      * */
     public android.support.v4.app.Fragment setArguments(int mode) {
          this.currentMode = mode; // режим по умолчанию
          return this;
     }

     /**
      * Используйте этот фабричный метод для создания новых экземпляров
      * этого фрагмента с использованием продоставленных параментров
      * (черт знает где эти "параметры", япросто перевел сгенерированный коммент)
      *
      * @return Новый объект фрагмента {@link MenuListFragment}.
      */
     // TODO: Переменуйте и измените типы и количество параметров (перевод)
     // TODO: разобраться зачем нужен этот метод
     public static MenuListFragment newInstance() {
          MenuListFragment fragment = new MenuListFragment();
          Bundle args = new Bundle();
          fragment.setArguments(args);
          return fragment;
     }

     @Override
     public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);

     }

     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
          setHasOptionsMenu(true); // у фрагмента имеются команды меню

          // Inflate the layout for this fragment
          if (currentMode == CARD_MODE) {
                return inflater.inflate(R.layout.fragment_menu_card_list, container, false);
          }else { // currentMode == PLATE_MODE
                return inflater.inflate(R.layout.fragment_menu_plates_list, container, false);
          }
     }

     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
          super.onActivityCreated(savedInstanceState);

          // TODO: Лучше ли это место для установки адаптера?
          // ArrayAdapter для связывания weatherList с weatherListView
          menuItemArrayAdapter = new MenuItemArrayAdapter(getActivity(), menuItemList);
          if (currentMode == CARD_MODE) {
                menuItemListListView = (ListView) getView().findViewById(R.id.cardList);
                menuItemListListView.setAdapter(menuItemArrayAdapter);
          }else { // currentMode == PLATE_MODE
                menuItemListGridView = (GridView) getView().findViewById(R.id.platesList);
                menuItemListGridView.setAdapter(menuItemArrayAdapter);
          }

          try {
                URL url = new URL("http://192.168.1.127/index.php");

                GetDataTask getLocalDataTask = new GetDataTask();
                getLocalDataTask.execute(url);
          }
          catch (Exception e) {
                e.printStackTrace();
          }
     }

     @Override
     public void onAttach(Context context) {
          super.onAttach(context);
          /*if (context instanceof OnFragmentInteractionListener) {
                mListener = (OnFragmentInteractionListener) context;
          } else {
                throw new RuntimeException(context.toString()
                          + " must implement OnFragmentInteractionListener");
          }*/
     }

     @Override
     public void onDetach() {
          super.onDetach();
          //mListener = null;
     }

     /**
      * Отображение команд меню фрагмента
      * @param menu Меню
      * @param inflater Инфлатер для меню
      */
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
          super.onCreateOptionsMenu(menu, inflater);
          inflater.inflate(R.menu.menu_list_menu, menu);
     }

     // Обработка выбора команд меню
     @Override
     public boolean onOptionsItemSelected(android.view.MenuItem item) {
          FragmentManager fm = getFragmentManager(); // Необходим для транзакий фрагментов: при удалении и заменене одного фрагмента другим

          // Выбор в зависимости от идентификатора MenuItem
          switch (item.getItemId()) {
                case R.id.shopping_cart:
                     return true; // Событие меню обработано
                case R.id.sort:
                     if (fm != null) {
                          /*
                          Perform the FragmentTransaction to load in the list tab content.
                          Using FragmentTransaction#replace will destroy any Fragments
                          currently inside R.id.fragment_content and add the new Fragment
                          in its place. (с) Google doc
                          */
                          FragmentTransaction ft = fm.beginTransaction(); // Начало транзакции
                          ( (ViewGroup) getActivity().findViewById(R.id.fragment_menu) ).removeAllViews(); // Удаляет View на экране (сам список)
                          ft.remove(this); // Удаляет кнопки на палени действий (TODO: и вместе с ним сам фрагмент?)

                          // Замена фрагмента
                          // TODO: Сделать так, чтобы разметка фрагмента менялась без пересоздания (читай удаления) макета
                          if (currentMode == CARD_MODE) {
                                ft.replace(R.id.fragment_menu, new MenuListFragment().setArguments(PLATE_MODE));
                          }else {// currentMode == PLATE_MODE
                                ft.replace(R.id.fragment_menu, new MenuListFragment().setArguments(CARD_MODE));

                          }
                          ft.commit(); // Завершение транзакции
                     }
                     return true; // Событие меню обработано
          }

          return super.onOptionsItemSelected(item); //TODO: Разобраться зачем вообще тут нужен супер
     }

     /**
      * Этот интерфейс должно быть реализован в активити, которая содержит этот
      * фрагмент, чтобы фрагмен смог взаимодействовать с активити
      * и ,возможно, с другими фрагментами, содержащиеся в этой активити.
      * <p>
      * Подробнее смотрите в Android Training lesson: <a href=
      * "http://developer.android.com/training/basics/fragments/communicating.html"
      * >Communicating with Other Fragments</a>
      * </p>.
      */
     // Закомментирован, т.к. еще не изучен
     /*public interface OnFragmentInteractionListener {
          // TODO: Update argument type and name
          void onFragmentInteraction(Uri uri);
     }*/

     /* Обращение к REST-совместимому (якобы) веб-сервису за данными блюд и меню
     и сохранение этих данных в локальном файле HTML */

     /**
      * Внутренний класс {@link AsyncTask} для загрузки данных
      * в формате JSON.
      * @author RareScrap
      */
     private class GetDataTask extends AsyncTask<URL, Void, JSONObject> {
          /**
            * Получение данных из сети
            * @param params URL для получения JSON файла
            * @return JSON файл с категориями меню и блюдами в них
            */
          @Override
          protected JSONObject doInBackground(URL... params) {
                HttpURLConnection connection = null;

                try {
                     connection = (HttpURLConnection) params[0].openConnection(); // Для выдачи запроса достаточно открыть объект подключения
                     int response = connection.getResponseCode(); // Получить код ответа от веб-сервера

                     if (response == HttpURLConnection.HTTP_OK) {
                          StringBuilder builder = new StringBuilder();

                          try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                                String line;
                                while ((line = reader.readLine()) != null) {
                                     builder.append(line);
                                }
                          }
                          catch (IOException e) {
                                e.printStackTrace();
                          }

                          return new JSONObject(builder.toString());
                     }else {
                     }
                }
                catch (Exception e) {
                     e.printStackTrace();
                }
                finally {
                     connection.disconnect(); // Закрыть HttpURLConnection
                }

                return null;
          }
          /**
            * Обработка ответа JSON и обновление ListView.
            *
            * @param jsonObject JSON файл полученный после завершения работы doInBackground()
            */
          @Override
          protected void onPostExecute(JSONObject jsonObject) {
                if (jsonObject != null) {
                     convertJSONtoArrayList(jsonObject); // Заполнение weatherList
                     menuItemArrayAdapter.notifyDataSetChanged(); // Связать с ListView

                     // Прокрутить до верха
                     if (currentMode == CARD_MODE) {
                          menuItemListListView.smoothScrollToPosition(0);
                     }else { // currentMode == PLATE_MODE
                          menuItemListGridView.smoothScrollToPosition(0);
                     }
                }
          }
     }

     /**
      * Создание объектов MenuItem на базе JSONObject
      * с последующим их заесением в menuItemList.
      *
      * @param jsonObject Входящий JSON файл
      */
     private void convertJSONtoArrayList(JSONObject jsonObject) {
          menuItemList.clear(); // Стирание старых погодных данных

          try {
                // Получение свойства "list" JSONArray
                JSONArray list = jsonObject.getJSONArray("sushi");

                // Преобразовать каждый элемент списка в объект Weather
                for (int i = 0; i < list.length(); ++i) {
                     JSONObject deash = list.getJSONObject(i); // Данные за день
                     // Получить JSONObject с температурами дня ("temp")
                     String name = deash.getString("name");

                     // Получить JSONObject c описанием и значком ("weather")
                     String picURL = deash.getString("picURL");

                     // Добавить новый объект Weather в weatherList
                     menuItemList.add( new MenuItem(name, picURL));
                }
          }
          catch (JSONException e) {
                e.printStackTrace();
          }
     }
}
android
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    RareScrap
    2020-04-04T17:02:25Z2020-04-04T17:02:25Z

    通过使用 LayoutInflater 并安装和更新适配器解决了该问题。对于错误的代码,我深表歉意,但是在考虑了一个星期的问题后,这个解决方案在一分钟前就出现了,而且它有效!

    // Обработка выбора команд меню
    @Override
    public boolean onOptionsItemSelected(android.view.MenuItem item) {
        FragmentManager fm = getFragmentManager(); // Необходим для транзакий фрагментов: при удалении и заменене одного фрагмента другим
    
        // Выбор в зависимости от идентификатора MenuItem
        switch (item.getItemId()) {
            case R.id.shopping_cart:
                return true; // Событие меню обработано
            case R.id.sort:
                if (fm != null) {
                    /*
                    Perform the FragmentTransaction to load in the list tab content.
                    Using FragmentTransaction#replace will destroy any Fragments
                    currently inside R.id.fragment_content and add the new Fragment
                    in its place. (с) Google doc
                    */
                    //FragmentTransaction ft = fm.beginTransaction(); // Начало транзакции
                    ( (ViewGroup) getActivity().findViewById(R.id.fragment_menu) ).removeAllViews(); // Удаляет View на экране (сам список)
                    //ft.remove(this); // Удаляет кнопки на палени действий (TODO: и вместе с ним сам фрагмент?)
    
                    // Замена фрагмента
                    // TODO: Сделать так, чтобы разметка фрагмента менялась без пересоздания (читай удаления) макета
                    if (currentMode == CARD_MODE) {
                        currentMode = PLATE_MODE;
                        //ft.replace(R.id.fragment_menu, new MenuListFragment().setArguments(PLATE_MODE));
                        LayoutInflater inflater = getActivity().getLayoutInflater();
                        int a = R.layout.fragment_menu_plates_list; // a и b Созданы, чтобы отслеживать их в отладчике
                        ViewGroup b =  (ViewGroup) this.getView();
                        View view = inflater.inflate(a, b, true); // Помещает разметку "a" как корневой элемент фрагмента
                        menuItemListGridView = (GridView) getView().findViewById(R.id.platesList);
                        menuItemListGridView.setAdapter(menuItemArrayAdapter);
                        menuItemArrayAdapter.notifyDataSetChanged(); // Связать с ListView
                    }else {// currentMode == PLATE_MODE
                        currentMode = CARD_MODE;
                        //ft.replace(R.id.fragment_menu, new MenuListFragment().setArguments(CARD_MODE));
                        LayoutInflater inflater = getActivity().getLayoutInflater();
                        int a = R.layout.fragment_menu_card_list;
                        ViewGroup b =  (ViewGroup) this.getView();
                        View view = inflater.inflate(a, b, true);
                        menuItemListListView = (ListView) getView().findViewById(R.id.cardList);
                        menuItemListListView.setAdapter(menuItemArrayAdapter);
                        menuItemArrayAdapter.notifyDataSetChanged(); // Связать с ListView
    
                    }
                    //ft.commit(); // Завершение транзакции
                }
                return true; // Событие меню обработано
        }
    
        return super.onOptionsItemSelected(item); //TODO: Разобраться зачем вообще тут нужен супер
    }
    
    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5