Как мне изменить вид внутри фрагмента? - PullRequest
40 голосов
/ 10 мая 2011

У меня есть фрагмент, который создает его представление внутри onCreateView, как и следовало ожидать.Однако я хочу периодически менять представление.

Мой вариант использования заключается в том, что фрагмент показывает некоторые данные из веб-службы.Когда пользователь выбирает параметр из списка (другой фрагмент), этот фрагмент должен переключиться на индикатор выполнения, а затем после загрузки переключиться обратно на представление данных.

Я мог бы сделать два фрагмента - загружаемый фрагмент,и отображающий фрагмент, но кажется, что, поскольку это инкапсулированное событие, я бы предпочел сделать все это внутри одного фрагмента.

По сути, я спрашиваю, что эквивалентно setContentView внутри фрагмента.

Ответы [ 9 ]

32 голосов
/ 26 мая 2011

Вы можете использовать Fragment.getView(). Это возвращает представление контейнера, который содержит Fragment. По этому поводу вы можете позвонить removeAllViews. Затем создайте новые представления и добавьте их в представление, полученное с getView().

.

http://developer.android.com/reference/android/app/Fragment.html#getView()

25 голосов
/ 16 ноября 2012

Если по какой-либо причине вы хотите изменить представление всего фрагмента (например, асинхронный запрос URL, который изменит представление в случае успеха), вы можете использовать FragmentTransaction в родительском действии и создать новый фрагмент на лету .

Или вы можете оставить фрагмент и вызвать метод этого фрагмента, который обновится сам. Пример: В родительском упражнении я строю и сохраняю список фрагментов List<RefreshFragment> mFragmentList.

Вот класс RefreshFragment (и все мои фрагменты расширяют этот в моем примере):

public class RefreshFragment extends Fragment {
    protected Data data; // here your asynchronously loaded data

    public void setData(Data data) {
        this.data = data;
        // The reload fragment code here !
        if (! this.isDetached()) {
            getFragmentManager().beginTransaction()
               .detach(this)
               .attach(this)
               .commit();
        }
    }
}

Тогда в моей деятельности асинхронный обратный вызов я могу назвать:

for (RefreshFragment f : mFragmentList) f.setData(data);

Таким образом, каждый фрагмент будет обновлен с правильными данными, и присоединенный в данный момент фрагмент будет обновлен немедленно. Вы должны предоставить свой собственный onCreateView во фрагментах, конечно.

Важно то, что фрагмент может перезагрузить себя с помощью getFragmentManager().

3 голосов
/ 23 августа 2011

Вы можете использовать FrameLayout для переключения между индикатором выполнения и просмотром данных, например,

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ImageView android:id="@+id/cover_image"
        android:scaleType="fitCenter"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
    <ProgressBar android:id="@+id/cover_progress"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_gravity="center"/>
</FrameLayout>

В onViewCreate() вы затем сохраните оба представления в полях экземпляра

public View onCreateView(LayoutInflater inflater,
        ViewGroup container, Bundle savedInstanceState) {
    ...
    image = (ImageView) container.findViewById(R.id.cover_image);
    progress = container.findViewById(R.id.cover_progress);
    ...
}

и всякий раз, когда вы хотите переключиться между ними (не забудьте сделать это в вашем пользовательском интерфейсе / главном потоке), просто сделайте что-то вроде

progress.setVisibility(View.INVISIBLE);
image.setVisibility(View.VISIBLE);
2 голосов
/ 22 мая 2016

Вот более простое решение: сохраните инфлятор и контейнер, полученный в onCreateView, и используйте их позже. Например:

private LayoutInflater mInflater;
private ViewGroup mRootView;

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    mInflater = inflater;
    mRootView = container;
    return null;
}

public void someCallBackLater() {
    // mRootView.removeAllViews();   // in case you call this callback again...
    mInflater.inflate(R.layout.my_layout, mRootView);
}
2 голосов
/ 14 апреля 2016

Создать "фиктивный" вид по умолчанию

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

</LinearLayout>

Раздвиньте «фиктивное» представление по умолчанию в методе фрагмента onCreateView и используйте его в качестве заполнителя для добавления представлений при необходимости

private LayoutInflater mInflater;
private ViewGroup mContainer;

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState){
    mInflater = inflater;
    mContainer = container;

    View v =inflater.inflate(R.layout.home_view,container,false);
    placeholder = (ViewGroup) v;

    return placeholder;
}

Чтобы изменить представление на новое представление, сначала удалите все предыдущие представления, а затем накачайте новое представление и добавьте

View newView = mInflater.inflate(R.layout.custom_dash, mContainer, false);
placeholder.removeAllViews();
placeholder.addView(newView);
1 голос
/ 23 августа 2014

Используя ответ Solostaran14s, я делаю это сейчас:

Интерфейс:

public interface FragmentReattachListener {

    public void reAttach();

}

Фрагмент:

public class MyFragment extends Fragment implements  FragmentReattachListener {
//...

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    //...
    App.registerFragmentReattachListener(this);
    //...
}

//...    

@Override
public void reAttach() {
    FragmentManager f = getFragmentManager();
    if (f != null) {
         f.beginTransaction()
                    .detach(this)
                    .attach(this)
                    .commit();
        }
    }

}

из класса приложения:

private static void reattachFragments() {
        if (fragmentReattachListeners.size() > 0) {
            for (FragmentReattachListener listener : fragmentReattachListeners) {
                listener.reAttach();
            }
        }
    }
1 голос
/ 30 июля 2012

U можете использовать транзакцию удаления и добавления.Я использовал фрагмент, в котором я могу загрузить любой вид.Конструктор фрагмента должен иметь целое число, это целое число - R.layout .... Я просто удаляю старый фрагмент и помещаю новый.!!!Это работает, только если вы сделаете этот фрагмент динамическим, а не в макете XML.Просто создайте что-то вроде LinearLayout R.id.fragment_layout

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.wundlist_fragmente);
    Log.v("WoundListActivity", "WoundListActivity gestartet...");

    Log.v("WoundListActivity", "Liste...");
    //dynamisch hinzufügen...
    wlf=new WoundListFragment();        
    fm.beginTransaction().add(R.id.fragment_layout,wlf).commit();

}

//If Menubutton Clicked change

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if(item.getItemId()==R.id.itemaddwound){
        Log.v("List", "neue Wunde Activity");

        fm.beginTransaction().remove(wlf).commit();
        fm.beginTransaction().add(R.id.fragment_layout, new NewWoundFragment()).commit();

    }

    return super.onOptionsItemSelected(item);
}
0 голосов
/ 18 января 2016

У меня та же проблема, frag.getView () всегда возвращает ноль, хотя Fragment.onCreateView уже вызывался до

мы не можем изменить содержимое фрагмента во время выполнения, потому что мой фрагмент был добавлен в ViewPager, поэтому я пытаюсь использовать другой метод, чтобы получить представление:

 View view  =  viewPager.getChildAt(0);
 TextView text = (TextView) (view.findViewById(R.id.textView));
 text.setText("12345");

Эта проблема теперь решена, я надеюсь, что она может помочь вам

0 голосов
/ 06 сентября 2013

Вот что у меня сработало:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.fragment_recipe, container, false);
    Button recipeBuyButton = (Button) v.findViewById(
            R.id.recipe_buy_button);
    Typeface tf = Typeface.createFromAsset(getActivity().getAssets(), "fonts/GE_SS_Two_Medium.otf");
    recipeBuyButton.setTypeface(tf);
    return v;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...