刷新或强制重绘片段。

56

我有一个片段可以填充XML布局。我的要求是当Activity恢复时,更新片段内所有视图的文本大小。我尝试过

    fragment.getView().invalidate();

似乎没有起作用。我还尝试了

    fragment.getView().requestLayout();

这也没有起作用。

在另一个活动中,我有一个ListFragment需要做同样的事情。 我尝试过

    listfragment.getListView().invalidate();

解决方法是通过刷新列表视图并重绘其中所有的项目来达到目的。

我不明白为什么一个可以工作而另一个不行。

我也看到有人建议初始化一个片段事务并用新的片段替换当前片段,这让我感到疑惑。

  1. 当我只需要刷新片段包含的视图上的文本时,为什么要创建一个全新的片段并替换我的当前片段呢?

  2. 片段事务的方法将阻止我在活动的布局XML中定义我的片段,我将不得不在正确的位置编程插入该片段。

有没有简单的方法解决这个问题呢?


更新TextView的已知属性,例如文本大小,不是您需要调用invalidate()的事情;当属性更改时,框架会为您执行此操作。也许展示一下您正在更新文本属性的代码;问题更可能出在那里。您唯一需要手动invalidate()视图的时间是如果您创建了Android不知道的自定义属性。 - devunwired
该片段负责在其包含的所有视图中加载数据,并在填充数据时检查用户从偏好设置中设置的文本大小,并在那时设置该大小。我认为,如果大小发生了显着变化,则视图必须调整自身以包裹内容,因此需要重新绘制。即使它是自定义属性而不是文本大小,我们如何强制片段视图重新绘制? - ps2010
当您设置文本值时,视图/布局系统知道它需要重新测量和重新绘制。只需查看TextView源代码中的setRawTextSize()(第2406行)...在更新属性后会调用什么?https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/widget/TextView.java 此外,invalidate()不会强制视图自适应,而是requestLayout()实现此功能。 - devunwired
我遇到了同样的问题。根据这里未回答的问题数量,我在想我是否真正理解View元素应该如何工作。 - Dan Devine
请帮帮我:https://stackoverflow.com/questions/61811228/refresh-oncreateview-fragment/61812231#61812231 - MexiCano
显示剩余4条评论
8个回答

29

我认为没有针对那种情况的方法。该片段会在onCreateView()上重新构建它的UI...但是这发生在片段被创建或重新创建时。

您将需要实现自己的updateUI方法,或在其中指定应如何更新哪些元素以及如何更新。这是一个很好的实践,因为您无论如何都需要在片段创建时执行此操作。

但是,如果这不足够,您可以尝试使用相同的片段替换片段并强制调用onCreateView()

FragmentTransaction tr = getFragmentManager().beginTransaction();
tr.replace(R.id.your_fragment_container, yourFragmentInstance);
tr.commit()

注意

要刷新ListView,您需要在ListView的适配器上调用notifyDataSetChanged()


这里有帮助:http://stackoverflow.com/questions/40095826/how-to-update-a-fragment-that-has-a-gridview-populated-from-sqlite/40096402?noredirect=1#comment67569523_40096402 - Si8

25
在我的情况下,detachattach 起了作用:
 getSupportFragmentManager()
   .beginTransaction()
   .detach(contentFragment)
   .attach(contentFragment)
   .commit();

原始文本已更新,包含了我的评论,因此我的评论不再相关,所以我将其删除。 - swooby
19
这个解决方案损坏了我的后退栈。 - ElizaS
是的,我只需要刷新一个适配器,分离和重新连接似乎有些过度(尽管它看起来是唯一的解决方案)。 - Alberto M

10

使用以下代码再次刷新片段:

FragmentTransaction ftr = getFragmentManager().beginTransaction();                          
ftr.detach(EnterYourFragmentName.this).attach(EnterYourFragmentName.this).commit();

10

detach().detach()在支持库更新至25.1.0(可能更早版本)后不起作用。 此解决方案在更新后可以正常工作:

getSupportFragmentManager()
    .beginTransaction()
    .detach(oldFragment)
    .commitNowAllowingStateLoss();

getSupportFragmentManager()
    .beginTransaction()
    .attach(oldFragment)
    .commitAllowingStateLoss();

在更新到新的支持库版本之前,一切都正常工作,但这个解决方案拯救了我!简要说明 - 我不得不使用runOnUiThread()来使用commitNowAllowingStateLoss,否则它无法正常工作。 - Anthony Hilyard

1
为了解决这个问题,我使用了这个代码:


Fragment frg = null;
frg = getFragmentManager().findFragmentByTag("Feedback");
final android.support.v4.app.FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(frg);
ft.attach(frg);
ft.commit();

标签在哪里?我该如何找到它?我正在向Sqlite数据库添加一些内容。完成后,我想从Activity刷新Fragment。 - Si8

0

在Fragment中,这对我有用:

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();

-1
让我们看下面的源代码。这里的片段名称是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();
            }

        }
    }

    }

-1

我正在使用删除和替换两种方法来刷新片段的内容,例如

final FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.remove(resetFragment).commit();
fragmentTransaction.replace(R.id.frame_container,resetFragment).commit();

你的建议导致了应用程序崩溃。 - Native_Mobile_Arch_Dev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接