Обновить или принудительно перерисовать фрагмент
У меня есть фрагмент, который раздувает xml-макет. Мое требование - обновлять размер текста во всех моих представлениях внутри моего фрагмента, когда моя активность возобновляется. Я попробовал
fragment.getView().invalidate();
который, похоже, не работал. Я также пробовал
fragment.getView().requestLayout();
который тоже не работает.
В другом действии у меня есть ListFragment, который должен делать то же самое. Я попробовал
listfragment.getListView().invalidate();
который сделал трюк, обновляя мое представление списка и перерисовывая все элементы внутри него.
Я не понимаю, почему один работает, но не другой.
Я также видел людей, рекомендующих инициировать транзакцию фрагмента и заменяя текущий фрагмент на новый, и это заставило меня задаться вопросом
-
Почему я должен создавать совершенно новый фрагмент и заменять свой текущий фрагмент, когда мне нужно только обновить текст в представлениях, которые содержит мой фрагмент.
-
Метод транзакции фрагментов не позволит мне определить мой фрагмент в макете xml моей активности, и мне придется программно вставлять фрагмент в нужную позицию.
Есть ли простой подход к этому?
Ответы
Ответ 1
Я не думаю, что для этого есть метод. Фрагмент восстанавливает его UI на onCreateView()... но это происходит, когда фрагмент создается или воссоздается.
Вам придется реализовать свой собственный метод updateUI или указать, какие элементы и как они должны обновляться. Это довольно хорошая практика, так как вам нужно это делать, когда фрагмент создается в любом случае.
Однако, если этого недостаточно, вы можете сделать что-то вроде замены фрагмента тем же, что и заставить его вызвать onCreateView()
FragmentTransaction tr = getFragmentManager().beginTransaction();
tr.replace(R.id.your_fragment_container, yourFragmentInstance);
tr.commit()
Примечание
Чтобы обновить ListView, вам нужно вызвать notifyDataSetChanged()
в адаптере ListView.
Ответ 2
В моем случае detach
и attach
работают для меня.
getSupportFragmentManager()
.beginTransaction()
.detach(contentFragment)
.attach(contentFragment)
.commit();
Ответ 3
detach().detach()
не работает после обновления библиотеки поддержки 25.1.0 (может быть раньше).
Это решение отлично работает после обновления:
getSupportFragmentManager()
.beginTransaction()
.detach(oldFragment)
.commitNowAllowingStateLoss();
getSupportFragmentManager()
.beginTransaction()
.attach(oldFragment)
.commitAllowingStateLoss();
Ответ 4
Чтобы решить проблему, я использую это:
Fragment frg = null;
frg = getFragmentManager().findFragmentByTag("Feedback");
final android.support.v4.app.FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(frg);
ft.attach(frg);
ft.commit();
Ответ 5
Это работало для меня изнутри фрагмента:
Fragment frg = null;
Class fragmentClass;
fragmentClass = MainFragment.class;
try {
frg = (android.support.v4.app.Fragment) fragmentClass.newInstance();
}catch(Exception ex){
ex.printStackTrace();
}
getFragmentManager().beginTransaction().replace(R.id.flContent, frg).commit();
Ответ 6
рассмотрим приведенный ниже исходный код. Здесь имя фрагмента - DirectoryOfEbooks.
После завершения фоновой задачи я заменяю кадр текущим фрагментом. поэтому фрагмент обновляется и перезагружает свои данные.
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.github.mikephil.charting.data.LineRadarDataSet;
import java.util.ArrayList;
import java.util.List;
/**
* A simple {@link Fragment} subclass.
*/
public class DirectoryOfEbooks extends Fragment {
RecyclerView recyclerView;
branchesAdapter adapter;
LinearLayoutManager linearLayoutManager;
Cursor c;
FragmentTransaction fragmentTransaction;
SQLiteDatabase db;
List<branch_sync> directoryarraylist;
public DirectoryOfEbooks() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_directory_of_ebooks, container, false);
directoryarraylist = new ArrayList<>();
db = getActivity().openOrCreateDatabase("notify", android.content.Context.MODE_PRIVATE, null);
c = db.rawQuery("select * FROM branch; ", null);
if (c.getCount() != 0) {
c.moveToFirst();
while (true) {
//String ISBN = c.getString(c.getColumnIndex("ISBN"));
String branch = c.getString(c.getColumnIndex("branch"));
branch_sync branchSync = new branch_sync(branch);
directoryarraylist.add(branchSync);
if (c.isLast())
break;
else
c.moveToNext();
}
recyclerView = (RecyclerView) view.findViewById(R.id.directoryOfEbooks);
adapter = new branchesAdapter(directoryarraylist, this.getContext());
adapter.setHasStableIds(true);
recyclerView.setItemAnimator(new DefaultItemAnimator());
System.out.println("ebooks");
recyclerView.setHasFixedSize(true);
linearLayoutManager = new LinearLayoutManager(this.getContext());
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(adapter);
System.out.println(adapter.getItemCount()+"adpater count");
}
// Inflate the layout for this fragment
return view;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.fragment_books);
setHasOptionsMenu(true);
}
public void onPrepareOptionsMenu(Menu menu) {
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.refresh, menu);
MenuItem menuItem = menu.findItem(R.id.refresh1);
menuItem.setVisible(true);
}
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.refresh1) {
new AlertDialog.Builder(getContext()).setMessage("Refresh takes more than a Minute").setPositiveButton("Refresh Now", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
new refreshebooks().execute();
}
}).setNegativeButton("Refresh Later", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
}).setCancelable(false).show();
}
return super.onOptionsItemSelected(item);
}
public class refreshebooks extends AsyncTask<String,String,String>{
ProgressDialog progressDialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog=new ProgressDialog(getContext());
progressDialog.setMessage("\tRefreshing Ebooks .....");
progressDialog.setCancelable(false);
progressDialog.show();
}
@Override
protected String doInBackground(String... params) {
Ebooksync syncEbooks=new Ebooksync();
String status=syncEbooks.syncdata(getContext());
return status;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if(s.equals("error")){
progressDialog.dismiss();
Toast.makeText(getContext(),"Refresh Failed",Toast.LENGTH_SHORT).show();
}
else{
fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.mainframe, new DirectoryOfEbooks());
fragmentTransaction.commit();
progressDialog.dismiss();
adapter.notifyDataSetChanged();
Toast.makeText(getContext(),"Refresh Successfull",Toast.LENGTH_SHORT).show();
}
}
}
}
Ответ 7
Используйте следующий код для повторного обновления фрагмента:
FragmentTransaction ftr = getFragmentManager().beginTransaction();
ftr.detach(EnterYourFragmentName.this).attach(EnterYourFragmentName.this).commit();
Ответ 8
Я использую remove и заменяю оба для обновления содержимого фрагмента, например
final FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.remove(resetFragment).commit();
fragmentTransaction.replace(R.id.frame_container,resetFragment).commit();