Как изменить представление внутри фрагмента?
У меня есть фрагмент, который создает его представление внутри onCreateView, как вы ожидали. Однако я хочу периодически менять представление.
Моим вариантом использования является то, что фрагмент показывает некоторые данные из веб-службы. Когда пользователь выбирает опцию из списка (другой фрагмент), этот фрагмент должен переключиться на индикатор выполнения, а затем после загрузки переключиться обратно в представление данных.
Я мог бы сделать два фрагмента - фрагмент загрузки и фрагмент отображения, но кажется, что, поскольку это инкапсулированное событие, я предпочел бы сделать все это внутри одного фрагмента.
В основном то, что я прошу, является тем, что является эквивалентом setContentView внутри фрагмента.
Ответы
Ответ 1
Вы можете использовать Fragment.getView()
. Это возвращает вид контейнера, который содержит Fragment
. С этой точки зрения вы можете вызвать removeAllViews
. Затем создайте новые представления и добавьте их в представление, которое вы получили от getView()
.
http://developer.android.com/reference/android/app/Fragment.html#getView()
Ответ 2
Если по какой-либо причине вы хотите изменить представление всего фрагмента (например, асинхронный запрос 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
Вы можете использовать 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);
Ответ 4
Создайте представление "dummy" по умолчанию
<?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>
Разверните представление "dummy" по умолчанию в методе 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);
Ответ 5
U может использовать Transaction remove и add. Я использовал фрагмент, в котором я могу загрузить любое представление.
Конструктор фрагмента должен иметь целое число, что целое число 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);
}
Ответ 6
Используя ответ Solostaran14s, я делаю это сейчас:
Интерфейс:
public interface FragmentReattachListener {
public void reAttach();
}
Fragment:
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();
}
}
}
из класса Application:
private static void reattachFragments() {
if (fragmentReattachListeners.size() > 0) {
for (FragmentReattachListener listener : fragmentReattachListeners) {
listener.reAttach();
}
}
}
Ответ 7
Здесь более простое решение: сохраните надув и контейнер, который вы получите в 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);
}
Ответ 8
Это сработало для меня:
@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;
Ответ 9
У меня одна и та же проблема, фрагмент .getView() всегда возвращает null, хотя Fragment.onCreateView уже вызывается перед
мы не можем изменить содержимое фрагмента во время выполнения, потому что мой фрагмент был добавлен в ViewPager, поэтому я пытаюсь использовать другой метод для просмотра:
View view = viewPager.getChildAt(0);
TextView text = (TextView) (view.findViewById(R.id.textView));
text.setText("12345");
Теперь эта проблема была решена, надеюсь, вам поможет