交换卡片时无法更新片段文本

Posted

技术标签:

【中文标题】交换卡片时无法更新片段文本【英文标题】:Not able to Update fragments text while swaping cards 【发布时间】:2017-05-17 19:47:12 【问题描述】:

我正在开发卡片刷卡和卡片翻转功能,我正在使用 ViewPager 和 Fragments。

我的问题是当我从左到右或从右到左刷卡时,我无法更新片段内的 TextView,但是当我翻转卡时它会更新 UI。 我尝试了互联网上可用的一切,但没有一个解决方案对我有用。

我正在关注此链接https://github.com/jamesmccann/android-view-pager-cards

这是我的代码

public class CardContainerFragment extends Fragment 

private boolean cardFlipped = false;
static TextView textview;

public CardContainerFragment() 
    setHasOptionsMenu(true);


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 

    View rootView = inflater.inflate(R.layout.fragment_card_container, container, false);
    LinearLayout ll = (LinearLayout)rootView.findViewById(R.id.layout);
    rootView.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            flipCard();
        
    );

    getChildFragmentManager()
            .beginTransaction()
            .add(R.id.container, new CardFrontFragment())
            .commit();

    Message msg = handler.obtainMessage();
    msg.arg1 = 1;
    handler.sendMessage(msg);

    return rootView;


final Handler handler = new Handler()
    @Override
    public void handleMessage(Message msg) 
        int page = CardActivity.mViewPager.getCurrentItem();
        int page_index = page+1;
        String current_page = page_index + " of " + card_activity.deck_map.size();
        CardActivity.tv.setText(current_page);


       super.handleMessage(msg);
    
;


public void flipCard() 
    Fragment newFragment = null;
    Message msg = handler.obtainMessage();
    msg.arg1 = 1;
    handler.sendMessage(msg);
    if (cardFlipped) 
        newFragment = new CardFrontFragment();
     else 
        newFragment = new CardBackFragment();
    

    getChildFragmentManager()
            .beginTransaction()
            .setCustomAnimations(
                    R.animator.card_flip_right_in, R.animator.card_flip_right_out,
                    R.animator.card_flip_left_in, R.animator.card_flip_left_out)
            .replace(R.id.container, newFragment)
            .commit();

    cardFlipped = !cardFlipped;


public static class CardFrontFragment extends Fragment 

    public CardFrontFragment()  

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 

        View rootView = inflater.inflate(R.layout.fragment_card, container, false);
        textview = (TextView)rootView.findViewById(R.id.card_front);
        String card_front_string = card_activity.arraylst.get(CardActivity.mViewPager.getCurrentItem());
        Log.e("current Item",CardActivity.mViewPager.getCurrentItem()+"");
        String complete_text = card_front_string +" \n \n + \n Tap now to flip this card.";
        textview.setText(complete_text);
        return rootView;
    


public static class CardBackFragment extends Fragment 

    public CardBackFragment()  

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 
        View rootView = inflater.inflate(R.layout.fragment_card_back, container, false);
        TextView textview = (TextView)rootView.findViewById(R.id.card_back);
        textview.setMovementMethod(new ScrollingMovementMethod());
        String card_front_string = card_activity.arraylst.get(CardActivity.mViewPager.getCurrentItem());
        String deck_data = card_activity.deck_map.get(card_front_string);
        textview.setText(deck_data);
        return rootView;
    

这是我的适配器代码

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    try 
        setContentView(R.layout.card_example);
        tv = (TextView)findViewById(R.id.tv_card_number);
        tv1 = (TextView)findViewById(R.id.tv_card_index);
        FragmentManager m = getFragmentManager();
        CardPagerAdapter adapter = new CardPagerAdapter(m);
        index = getIntent().getStringExtra("index");
        card_activity.cardCounter = Integer.parseInt(index);
        int count = card_activity.cardCounter;
        int final_count = count+1;
        String current_page = final_count+" of "+card_activity.deck_map.size();
        //CardActivity.tv.setText(current_page);
        mViewPager = (ViewPager) findViewById(R.id.view_pager);
       // mViewPager.setAllowedSwipeDirection(CustomViewPager.SwipeDirection.all);
        mViewPager.setAdapter(adapter);
        mViewPager.setCurrentItem(card_activity.cardCounter);
        //mViewPager.setOffscreenPageLimit(1);

        //mViewPager.setOnPageChangeListener(new pagechangelistener())


        //Log.e("current Item",CardActivity.mViewPager.getCurrentItem()+"");

    catch(Exception e)
        e.printStackTrace();
    


public class CardPagerAdapter extends android.support.v13.app.FragmentStatePagerAdapter 

    public CardPagerAdapter(FragmentManager fm) 
        super(fm);
    

    @Override
    public Fragment getItem(int i) 
        mViewPager.setOffscreenPageLimit(0);
        int page = mViewPager.getCurrentItem();
        int page_index = page+1;
        String current_page = " of " + card_activity.deck_map.size();
        tv.setText(current_page);
        tv1.setText(String.valueOf(page_index));
        CardContainerFragment cardContainerFragment = new CardContainerFragment();
        cardContainerFragment.current_index_front = page;
        cardContainerFragment.current_index_back = page;

        String card_front_string = card_activity.arraylst.get(page);
        CardContainerFragment.complete_text_front = card_front_string +" \n \n + \n Tap now to flip this card.";
        Bundle b = new Bundle();
        b.putInt("index",page);
        CardContainerFragment.complete_text_back = card_activity.deck_map.get(card_front_string);
        cardContainerFragment.setArguments(b);
        return cardContainerFragment;
    

    @Override
    public int getCount() 
        int len = card_activity.deck_map.size();
        return len;
    
    @Override
    public int getItemPosition(Object object) 
        return POSITION_NONE;
    

请让我知道我在这里做错了什么。

提前致谢

【问题讨论】:

不要使用静态字段CardActivity.mViewPager。见developer.android.com/guide/components/… @suneel 您能否详细说明您的问题(使用您的应用程序、xml 或其他内容的一些屏幕截图)?我无法理解确切的问题。 @TdSoft 我附上了一些截图并更新了我的问题,请看一下。 【参考方案1】:

我终于能够通过一些努力做到这一点。

经过搜索,我知道getItemsCardPagerAdapter中的方法)被调用了两次,因为Android为平滑过渡创建了一个额外的片段,而我从getItems发送或获取了错误的片段位置。

通过让机器人创建一个额外的片段并发送正确的位置,我能够解决这个问题。

这是我更新的代码

public class CardActivity extends android.support.v4.app.FragmentActivity 

public TextView tv;
public static String index=null;
public static ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    try 
        setContentView(R.layout.card_example);
        tv = (TextView)findViewById(R.id.tv_card_number);
        FragmentManager m = getFragmentManager();
        CardPagerAdapter adapter = new CardPagerAdapter(m);
        index = getIntent().getStringExtra("index");
        card_activity.cardCounter = Integer.parseInt(index);
        int count = card_activity.cardCounter;
        int final_count = count+1;
        String current_page = final_count+" of "+card_activity.deck_map.size();
        mViewPager = (ViewPager) findViewById(R.id.view_pager);
        mViewPager.setOffscreenPageLimit(0);
        mViewPager.setAdapter(adapter);
        mViewPager.setCurrentItem(card_activity.cardCounter);
        String current_page_temp =final_count+" of " + card_activity.deck_map.size();
        tv.setText(current_page_temp);

        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() 
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) 

            

            @Override
            public void onPageSelected(int position) 
                Log.e("aaa",position+"");
                    String current_page = position+1 + " of " + card_activity.deck_map.size();
                    tv.setText(current_page);
            

            @Override
            public void onPageScrollStateChanged(int state) 

            
        );
    catch(Exception e)
        e.printStackTrace();
    


    public class CardPagerAdapter extends android.support.v13.app.FragmentStatePagerAdapter 

    public CardPagerAdapter(FragmentManager fm) 
        super(fm);
    

    @Override
    public Fragment getItem(int i) 

        CardContainerFragment cardContainerFragment = new CardContainerFragment();
        Bundle b = new Bundle();
        b.putInt("index",i);
        cardContainerFragment.setArguments(b);
        return cardContainerFragment;
    

    @Override
    public int getCount() 
        int len = card_activity.deck_map.size();
        return len;
    
    @Override
    public int getItemPosition(Object object) 
        return POSITION_NONE;
    

  

================================================ ====================

public class CardContainerFragment extends Fragment 

private boolean cardFlipped = false;
int current_index=0;
static int pos = 0;
public CardContainerFragment() 
    /*setHasOptionsMenu(true);*/


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 

    View rootView = inflater.inflate(R.layout.fragment_card_container, container, false);
    LinearLayout ll = (LinearLayout)rootView.findViewById(R.id.layout);
    rootView.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            flipCard();
        
    );
    pos = getArguments().getInt("index");
    getChildFragmentManager()
            .beginTransaction()
            .add(R.id.container, new CardFrontFragment().newInstance(pos))
            .commit();
    card_activity.tempCounter = card_activity.tempCounter+1;
    return rootView;



public void flipCard() 
    Fragment newFragment = null;
    CardFrontFragment cardFrontFragment = null;
    CardBackFragment cardBackFragment = null;

    if (cardFlipped) 
        newFragment = CardFrontFragment.newInstance(CardActivity.mViewPager.getCurrentItem());
     else 
        newFragment = cardBackFragment.newInstance(CardActivity.mViewPager.getCurrentItem());
    

    getChildFragmentManager()
            .beginTransaction()
            .setCustomAnimations(
                    R.animator.card_flip_right_in, R.animator.card_flip_right_out,
                    R.animator.card_flip_left_in, R.animator.card_flip_left_out)
            .replace(R.id.container, newFragment)
            .commit();

    cardFlipped = !cardFlipped;

public static class CardBackFragment extends Fragment 

    public CardBackFragment()  

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 
        View rootView_back = inflater.inflate(R.layout.fragment_card_back, container, false);
        TextView textview_back = (TextView)rootView_back.findViewById(R.id.card_back);
        textview_back.setMovementMethod(new ScrollingMovementMethod());
        String text = getArguments().getString("back_text");
        textview_back.setText(text);

        return rootView_back;
    
    static CardBackFragment newInstance(int position) 
        CardBackFragment cardBackFragment = new CardBackFragment();
        Bundle args = new Bundle();
        String card_front_string = card_activity.arraylst.get(position);
        String text = card_activity.deck_map.get(card_front_string);
        args.putString("back_text", text);
        cardBackFragment.setArguments(args);
        return cardBackFragment;
    


public static class CardFrontFragment extends Fragment 

    public CardFrontFragment()  

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 
        View rootView_front = null;
        rootView_front = inflater.inflate(R.layout.fragment_card, container, false);
        TextView textview_front = (TextView)rootView_front.findViewById(R.id.card_front);
        String text = getArguments().getString("front_text");
        textview_front.setText(text);

        return rootView_front;
    

    static CardFrontFragment newInstance(int position) 
        CardFrontFragment cardFrontFragment = new CardFrontFragment();
        Bundle args = new Bundle();
        String card_front_string = card_activity.arraylst.get(position);
        String text = card_front_string +" \n \n + \n Tap now to flip this card.";
        args.putString("front_text", text);
        cardFrontFragment.setArguments(args);
        return cardFrontFragment;
    



 

【讨论】:

我很高兴你能回答你自己的问题@suneel。干得好! 非常感谢。【参考方案2】:

正如@david-rawson 所说

不要使用静态字段 CardActivity.mViewPager。见https://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity

这样做的原因是 ViewPager 可能/将在您的片段显示之前创建它们的视图,以确保您获得人们喜欢 ViewPager 的流畅动画。所以mViewPager同时调用了多个片段createView()函数,此时mViewPager有一个.getCurrentItem()的索引,该索引指向正在查看的页面上的CardContainer。

更好的选择是传递CardContainerFragment 带有“completeText”值的字符串参数,您希望它在创建CardBackFragmentCardFrontFragment 时显示该参数。

通过this了解更多详情。

【讨论】:

【参考方案3】:

您只需将数据设置为 CardFrontFragment 中使用的文本视图。 每当发生滑动时,就会调用 CardContainerFragment 的 onCreateView() 。 每次调用 onCreateView() 时,您都在添加 CardFrontFragment。您需要使用 CardFrontFragment 的文本视图,而不是使用活动的文本视图。

只需替换CardActivity.tv.setText(current_page);

textView.setText(current_page);

确保您在 CardFrontFragment 中使用的 textview 在类级别可用。

您使用的是静态片段,因此 textview 必须是静态的。

 private static TextView textView=null;

希望这对你有用:)

【讨论】:

【参考方案4】:

你试过了吗:

    tv.post(new Runnable() 
        @Override
        public void run() 
            CardActivity.tv.setText(current_page);
        
    );

【讨论】:

【参考方案5】:

我在我的应用程序中做了类似的事情,我使用开关盒管理我的 TextView 到 OnCreateView 中的显示。

我试图实现你的代码,但没有你的所有材料(如自定义动画师)。

然后你应该尝试这样的事情:

public class CardContainerFragment extends AppCompatActivity 

private boolean cardFlipped = false;
static TextView textview;

/*public CardContainerFragment() 
    setHasOptionsMenu(true);
*/

@Override
protected void onCreate(Bundle savedInstanceState) 

    super.onCreate(savedInstanceState);

    setContentView(R.layout.your_activity_name);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    // Create the adapter that will return a fragment for each of the three
    // primary sections of the activity.
    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    /*
  The @link ViewPager that will host the section contents.
 */
    ViewPager mViewPager = (ViewPager) findViewById(R.id.container);
    mViewPager.setAdapter(mSectionsPagerAdapter);

    mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() 
        // This method will be invoked when a new page becomes selected.
        @Override
        flipCard();

        @Override
        public void onPageSelected(int position) 

        

        // This method will be invoked when the current page is scrolled
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) 
            // Code goes here
        

        // Called when the scroll state changes:
        // SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING
        @Override
        public void onPageScrollStateChanged(int state) 
            // Code goes here
        
    );


@Override
public boolean onCreateOptionsMenu(Menu menu) 
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_welcome, menu);
    return true;


@Override
public boolean onOptionsItemSelected(MenuItem item) 
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) 
        return true;
    

    return super.onOptionsItemSelected(item);


/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment 
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";

    public PlaceholderFragment() 
    

    /**
     * Returns a new instance of this fragment for the given section
     * number.
     */
    public static PlaceholderFragment newInstance(int sectionNumber) 
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 

        //Initializing data
        Context context = getContext();

        View rootView = inflater.inflate(R.layout.fragment_card, container, false);
        TextView textView = (TextView) rootView.findViewById(R.id.txtView);

        int fragment = getArguments().getInt(ARG_SECTION_NUMBER);

        switch (fragment)
        
            case 1: //front card

                String card_front_string = card_activity.arraylst.get(CardActivity.mViewPager.getCurrentItem());
                Log.e("current Item",CardActivity.mViewPager.getCurrentItem()+"");
                String complete_text = card_front_string +" \n \n + \n Tap now to flip this card.";
                textview.setText(complete_text);

                getChildFragmentManager()
                        .beginTransaction()
                        .add(R.id.container, new CardFrontFragment())
                        .commit();

                Message msg = handler.obtainMessage();
                msg.arg1 = 1;
                handler.sendMessage(msg);

                return rootView;

            case 2: //back card

                TextView textview = (TextView)rootView.findViewById(R.id.card_back);
                textview.setMovementMethod(new ScrollingMovementMethod());
                String card_front_string = card_activity.arraylst.get(CardActivity.mViewPager.getCurrentItem());
                String deck_data = card_activity.deck_map.get(card_front_string);
                textview.setText(deck_data);

                getChildFragmentManager()
                        .beginTransaction()
                        .add(R.id.container, new CardFrontFragment())
                        .commit();

                Message msg = handler.obtainMessage();
                msg.arg1 = 1;
                handler.sendMessage(msg);

                return rootView;

            default:

                return rootView;

        
    



final Handler handler = new Handler()
    @Override
    public void handleMessage(Message msg) 
        int page = CardActivity.mViewPager.getCurrentItem();
        int page_index = page+1;
        String current_page = page_index + " of " + card_activity.deck_map.size();
        CardActivity.tv.setText(current_page);


       super.handleMessage(msg);
    
;


public void flipCard() 
    Message msg = handler.obtainMessage();
    msg.arg1 = 1;
    handler.sendMessage(msg);

    getChildFragmentManager()
            .beginTransaction()
            .setCustomAnimations(
                    R.animator.card_flip_right_in, R.animator.card_flip_right_out,
                    R.animator.card_flip_left_in, R.animator.card_flip_left_out)
            .replace(R.id.container, newFragment)
            .commit();


/**
 * A @link FragmentPagerAdapter that returns a fragment corresponding to
 * one of the sections/tabs/pages.
 */
public class SectionsPagerAdapter extends FragmentPagerAdapter 

    SectionsPagerAdapter(FragmentManager fm) 
        super(fm);
    

    @Override
    public Fragment getItem(int position) 
        // getItem is called to instantiate the fragment for the given page.
        // Return a PlaceholderFragment (defined as a static inner class below).
        return PlaceholderFragment.newInstance(position + 1);
    

    @Override
    public int getCount() 
        // Show 2 total pages.
        return 2;
    

    @Override
    public CharSequence getPageTitle(int position) 
        switch (position) 
            case 0:
                return "SECTION 1";
            case 1:
                return "SECTION 2";
        
        return null;
    

textview显示在您的页面上,并在选择更改时,将更改TextView的内容。

【讨论】:

如果您可以查看我的代码,是否可以。我可以给您访问权限。

以上是关于交换卡片时无法更新片段文本的主要内容,如果未能解决你的问题,请参考以下文章

无法从子类更新 UI

同步到交换帐户时,iOS 无法更新日历事件

无法更新 View Pager 中的中间片段。

片段 TextView 无法从 parcelable 对象更新

SecurityError:replaceState 无法将历史记录更新为在路径、查询或片段以外的组件中不同的 URL

无法更新FragmentPagerAdapter中的片段