ViewPager,ActionBar,Fragment应用--模仿通讯录滑动效果

最近由Android2.3切换到Android4.0的开发,一下子居然有点不适应,Android4.0新增了一些功能模块如ActionBar,Fragment等其实在Android3.0就有了,但一直没有做过平板上的开发,所以对这些模块非常陌生,一下子感觉Android4.0的开发难度甚大,经过十来天的努力,终于略微有所悟,在看通讯录的时候,感觉如果将其效果模仿出来岂不是初步达到掌握这些模块。

先看图,再列举出代码:

按住左右滑动时会自动切换。

源代码下载:http://download.csdn.net/detail/hjj0212/5023509

主要代码如下:

[java]  view plain copy
  1. package com.example.testtabactionbar;  
  2.   
  3. import android.net.Uri;  
  4. import android.os.Bundle;  
  5. import android.os.Parcelable;  
  6. import android.provider.ContactsContract.Contacts;  
  7. import android.app.ActionBar;  
  8. import android.app.Activity;  
  9. import android.app.Fragment;  
  10. import android.app.FragmentManager;  
  11. import android.app.FragmentTransaction;  
  12. import android.app.ListFragment;  
  13. import android.app.ActionBar.Tab;  
  14. import android.app.LoaderManager.LoaderCallbacks;  
  15. import android.content.CursorLoader;  
  16. import android.content.Loader;  
  17. import android.database.Cursor;  
  18. import android.support.v4.view.PagerAdapter;  
  19. import android.support.v4.view.ViewPager;  
  20. import android.text.TextUtils;  
  21. import android.util.Log;  
  22. import android.view.ContextMenu;  
  23. import android.view.LayoutInflater;  
  24. import android.view.Menu;  
  25. import android.view.MenuItem;  
  26. import android.view.View;  
  27. import android.view.ViewGroup;  
  28. import android.view.ContextMenu.ContextMenuInfo;  
  29. import android.widget.ArrayAdapter;  
  30. import android.widget.ListView;  
  31. import android.widget.SimpleCursorAdapter;  
  32. import android.widget.Toast;  
  33. import android.widget.SearchView.OnQueryTextListener;  
  34.   
  35. public class MainActivity extends Activity {  
  36.     private ActionBar mActionBar;  
  37.     private static final TabState DEFAULT_TAB = TabState.GROUPS;  
  38.     private TabState mCurrentTab = DEFAULT_TAB;  
  39.     private final MyTabListener mTabListener = new MyTabListener();  
  40.     private ArraListFragment mArrayFragment;  
  41.     private CursorLoaderFragment mCursorFragment;  
  42.     private ContextMenuFragment mContextMenuFragment;  
  43.     private ViewPager mTabPager;  
  44.     private TabPagerAdapter mTabPagerAdapter;     
  45.     private final TabPagerListener mTabPagerListener = new TabPagerListener();  
  46.       
  47.     @Override  
  48.     protected void onCreate(Bundle savedInstanceState) {  
  49.         super.onCreate(savedInstanceState);  
  50.         setContentView(R.layout.tab_view_pager);  
  51.         initActionBar();  
  52.         createViewAndFragment();  
  53.     }  
  54.       
  55.     private void createViewAndFragment(){  
  56.         final FragmentManager fragmentManager = getFragmentManager();  
  57.         final FragmentTransaction transaction = fragmentManager.beginTransaction();  
  58.           
  59.         mTabPager = getView(R.id.tab_pager);  
  60.         mTabPagerAdapter = new TabPagerAdapter();  
  61.         mTabPager.setAdapter(mTabPagerAdapter);  
  62.         mTabPager.setOnPageChangeListener(mTabPagerListener);  
  63.   
  64.         final String FAVORITE_TAG = "tab-pager-favorite";  
  65.         final String ALL_TAG = "tab-pager-all";  
  66.         final String GROUPS_TAG = "tab-pager-groups";  
  67.   
  68.         // Create the fragments and add as children of the view pager.  
  69.         // The pager adapter will only change the visibility; it'll never create/destroy  
  70.         // fragments.  
  71.         // However, if it's after screen rotation, the fragments have been re-created by  
  72.         // the fragment manager, so first see if there're already the target fragments  
  73.         // existing.  
  74.         mContextMenuFragment = (ContextMenuFragment) fragmentManager  
  75.                 .findFragmentByTag(FAVORITE_TAG);  
  76.         mArrayFragment = (ArraListFragment) fragmentManager  
  77.                 .findFragmentByTag(ALL_TAG);  
  78.         mCursorFragment = (CursorLoaderFragment) fragmentManager  
  79.                 .findFragmentByTag(GROUPS_TAG);  
  80.   
  81.         if (mContextMenuFragment == null) {  
  82.             Log.e("HJJ""ContextMenuFragmentd == null");  
  83.             mContextMenuFragment = new ContextMenuFragment();  
  84.             mArrayFragment = new ArraListFragment();  
  85.             mCursorFragment = new CursorLoaderFragment();  
  86.   
  87.             transaction.add(R.id.tab_pager, mContextMenuFragment, FAVORITE_TAG);  
  88.             transaction.add(R.id.tab_pager, mArrayFragment, ALL_TAG);  
  89.             transaction.add(R.id.tab_pager, mCursorFragment, GROUPS_TAG);  
  90.         }  
  91.   
  92.         // Hide all fragments for now. We adjust visibility when we get  
  93.         // onSelectedTabChanged()  
  94.         // from ActionBarAdapter.  
  95.         transaction.hide(mContextMenuFragment);  
  96.         transaction.hide(mArrayFragment);  
  97.         transaction.hide(mCursorFragment);  
  98.           
  99.         transaction.commitAllowingStateLoss();  
  100.         fragmentManager.executePendingTransactions();  
  101.     }  
  102.       
  103.     private class TabPagerListener implements ViewPager.OnPageChangeListener {  
  104.         @Override  
  105.         public void onPageScrollStateChanged(int state) {  
  106.         }  
  107.   
  108.         @Override  
  109.         public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {  
  110.         }  
  111.   
  112.         @Override  
  113.         public void onPageSelected(int position) {  
  114.             // Make sure not in the search mode, in which case position != TabState.ordinal().  
  115.             TabState selectedTab = TabState.fromInt(position);  
  116.             setCurrentTab(selectedTab, false);  
  117.             invalidateOptionsMenu();  
  118.         }  
  119.     }  
  120.       
  121.     private void initActionBar(){  
  122.         mActionBar = getActionBar();  
  123.         mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);  
  124.         // 去掉默认标题栏  
  125.         mActionBar.setDisplayShowHomeEnabled(false);    
  126.         mActionBar.setDisplayShowTitleEnabled(false);   
  127.         // Set up tabs  
  128.         addTab(TabState.GROUPS, R.drawable.ic_tab_groups);  
  129.         addTab(TabState.ALL, R.drawable.ic_tab_all);  
  130.         addTab(TabState.FAVORITES, R.drawable.ic_tab_starred);  
  131.     }  
  132.       
  133.     private class TabPagerAdapter extends PagerAdapter {  
  134.         private final FragmentManager mFragmentManager;  
  135.         private FragmentTransaction mCurTransaction = null;  
  136.   
  137.         private boolean mTabPagerAdapterSearchMode;  
  138.   
  139.         private Fragment mCurrentPrimaryItem;  
  140.   
  141.         public TabPagerAdapter() {  
  142.             mFragmentManager = getFragmentManager();  
  143.         }  
  144.   
  145.         @Override  
  146.         public int getCount() {  
  147.             return mTabPagerAdapterSearchMode ? 1 : TabState.values().length;  
  148.         }  
  149.   
  150.         /** Gets called when the number of items changes. */  
  151.         @Override  
  152.         public int getItemPosition(Object object) {  
  153.             if (mTabPagerAdapterSearchMode) {  
  154.                 if (object == mArrayFragment) {  
  155.                     return 0// Only 1 page in search mode  
  156.                 }  
  157.             } else {  
  158.                 if (object == mContextMenuFragment) {  
  159.                     return TabState.FAVORITES.ordinal();  
  160.                 }  
  161.                 if (object == mArrayFragment) {  
  162.                     return TabState.ALL.ordinal();  
  163.                 }  
  164.                 if (object == mCursorFragment) {  
  165.                     return TabState.GROUPS.ordinal();  
  166.                 }  
  167.             }  
  168.             return POSITION_NONE;  
  169.         }  
  170.   
  171.         @Override  
  172.         public void startUpdate(View container) {  
  173.         }  
  174.   
  175.         private Fragment getFragment(int position) {  
  176.             if (position == TabState.FAVORITES.ordinal()) {  
  177.                 return mContextMenuFragment;  
  178.             } else if (position == TabState.ALL.ordinal()) {  
  179.                 return mArrayFragment;  
  180.             } else if (position == TabState.GROUPS.ordinal()) {  
  181.                 return mCursorFragment;  
  182.             }  
  183.             throw new IllegalArgumentException("position: " + position);  
  184.         }  
  185.   
  186.         @Override  
  187.         public Object instantiateItem(View container, int position) {  
  188.             if (mCurTransaction == null) {  
  189.                 mCurTransaction = mFragmentManager.beginTransaction();  
  190.             }  
  191.             Fragment f = getFragment(position);  
  192.             mCurTransaction.show(f);  
  193.   
  194.             // Non primary pages are not visible.  
  195.             //f.setUserVisibleHint(f == mCurrentPrimaryItem);  
  196.             return f;  
  197.         }  
  198.   
  199.         @Override  
  200.         public void destroyItem(View container, int position, Object object) {  
  201.             if (mCurTransaction == null) {  
  202.                 mCurTransaction = mFragmentManager.beginTransaction();  
  203.             }  
  204.             mCurTransaction.hide((Fragment) object);  
  205.         }  
  206.   
  207.         @Override  
  208.         public void finishUpdate(View container) {  
  209.             if (mCurTransaction != null) {  
  210.                 mCurTransaction.commitAllowingStateLoss();  
  211.                 mCurTransaction = null;  
  212.                 mFragmentManager.executePendingTransactions();  
  213.             }  
  214.         }  
  215.   
  216.         @Override  
  217.         public boolean isViewFromObject(View view, Object object) {  
  218.             return ((Fragment) object).getView() == view;  
  219.         }  
  220.   
  221.         @Override  
  222.         public void setPrimaryItem(View container, int position, Object object) {  
  223.             Fragment fragment = (Fragment) object;  
  224.             if (mCurrentPrimaryItem != fragment) {  
  225.                 if (mCurrentPrimaryItem != null) {  
  226.                     //mCurrentPrimaryItem.setUserVisibleHint(false);  
  227.                 }  
  228.                 if (fragment != null) {  
  229.                     //fragment.setUserVisibleHint(true);  
  230.                 }  
  231.                 mCurrentPrimaryItem = fragment;  
  232.             }  
  233.         }  
  234.   
  235.         @Override  
  236.         public Parcelable saveState() {  
  237.             return null;  
  238.         }  
  239.   
  240.         @Override  
  241.         public void restoreState(Parcelable state, ClassLoader loader) {  
  242.         }  
  243.     }  
  244.       
  245.     @SuppressWarnings("unchecked")  
  246.     public <T extends View> T getView(int id) {  
  247.         T result = (T)findViewById(id);  
  248.         if (result == null) {  
  249.             throw new IllegalArgumentException("view 0x" + Integer.toHexString(id)  
  250.                     + " doesn't exist");  
  251.         }  
  252.         return result;  
  253.     }  
  254.       
  255.     protected static void showFragment(FragmentTransaction ft, Fragment f) {  
  256.         if ((f != null) && f.isHidden()) ft.show(f);  
  257.     }  
  258.   
  259.     protected static void hideFragment(FragmentTransaction ft, Fragment f) {  
  260.         if ((f != null) && !f.isHidden()) ft.hide(f);  
  261.     }  
  262.       
  263.     private void addTab(TabState tabState, int icon) {  
  264.         final Tab tab = mActionBar.newTab();  
  265.         tab.setTag(tabState);  
  266.         tab.setTabListener(mTabListener);  
  267.         tab.setIcon(icon);  
  268.         mActionBar.addTab(tab);  
  269.     }  
  270.   
  271.     public enum TabState {  
  272.         GROUPS, ALL, FAVORITES;  
  273.   
  274.         public static TabState fromInt(int value) {  
  275.             if (GROUPS.ordinal() == value) {  
  276.                 return GROUPS;  
  277.             }  
  278.             if (ALL.ordinal() == value) {  
  279.                 return ALL;  
  280.             }  
  281.             if (FAVORITES.ordinal() == value) {  
  282.                 return FAVORITES;  
  283.             }  
  284.             throw new IllegalArgumentException("Invalid value: " + value);  
  285.         }  
  286.     }  
  287.       
  288.     private class MyTabListener implements ActionBar.TabListener {  
  289.         /** 
  290.          * If true, it won't call {@link #setCurrentTab} in {@link #onTabSelected}. 
  291.          * This flag is used when we want to programmatically update the current tab without 
  292.          * {@link #onTabSelected} getting called. 
  293.          */  
  294.         public boolean mIgnoreTabSelected;  
  295.   
  296.         @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { }  
  297.         @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { }  
  298.   
  299.         @Override public void onTabSelected(Tab tab, FragmentTransaction ft) {  
  300.             Log.e("HJJ""onTabSelected..tag:" + tab.getTag());  
  301.             if (!mIgnoreTabSelected) {  
  302.                 setCurrentTab((TabState)tab.getTag());  
  303.             }  
  304.         }  
  305.     }  
  306.   
  307.     /** 
  308.      * Change the current tab, and notify the listener. 
  309.      */  
  310.     public void setCurrentTab(TabState tab) {  
  311.         setCurrentTab(tab, true);  
  312.     }  
  313.   
  314.     /** 
  315.      * Change the current tab 
  316.      */  
  317.     public void setCurrentTab(TabState tab, boolean notifyListener) {  
  318.         if (tab == nullthrow new NullPointerException();  
  319.         //实际上按照Contacts中的设计,这个是应该有效的,但在此模拟程序中,它会出现问题,因此暂时将此段去掉  
  320. //        if (tab == mCurrentTab) {  
  321. //            return;  
  322. //        }  
  323.         mCurrentTab = tab;  
  324.   
  325.         int index = mCurrentTab.ordinal();  
  326.         if ((mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS)  
  327.                 && (index != mActionBar.getSelectedNavigationIndex())) {  
  328.             mActionBar.setSelectedNavigationItem(index);  
  329.         }  
  330.   
  331.         if (notifyListener) onSelectedTabChanged(tab);  
  332.     }  
  333.       
  334.     private void onSelectedTabChanged(TabState tab){  
  335.         FragmentManager fragmentManager = getFragmentManager();  
  336.         FragmentTransaction ft = fragmentManager.beginTransaction();  
  337.         int tabIndex = tab.ordinal();  
  338.         Log.e("HJJ""tabIndex:" + tabIndex);  
  339.         switch (tab) {  
  340.         case FAVORITES:  
  341.             if(mContextMenuFragment!=null){  
  342.                 mTabPager.setCurrentItem(tabIndex, false);  
  343.             }  
  344.             showFragment(ft, mContextMenuFragment);  
  345.             hideFragment(ft, mArrayFragment);  
  346.             hideFragment(ft, mCursorFragment);  
  347.             break;  
  348.         case ALL:  
  349.             if(mArrayFragment!=null){  
  350.                 mTabPager.setCurrentItem(tabIndex, false);  
  351.             }  
  352.             hideFragment(ft, mContextMenuFragment);  
  353.             hideFragment(ft, mCursorFragment);  
  354.             showFragment(ft, mArrayFragment);  
  355.             break;  
  356.         case GROUPS:  
  357.             if(mCursorFragment!=null){  
  358.                 mTabPager.setCurrentItem(tabIndex, false);  
  359.             }  
  360.             hideFragment(ft, mContextMenuFragment);  
  361.             hideFragment(ft, mArrayFragment);  
  362.             showFragment(ft, mCursorFragment);  
  363.             break;  
  364.         }  
  365.         if (!ft.isEmpty()) {  
  366.             Log.e("HJJ""not ft isEmpty");  
  367.             ft.commitAllowingStateLoss();  
  368.             fragmentManager.executePendingTransactions();  
  369.             // When switching tabs, we need to invalidate options menu, but executing a  
  370.             // fragment transaction does it implicitly.  We don't have to call invalidateOptionsMenu  
  371.             // manually.  
  372.         }  
  373.     }  
  374.       
  375.       
  376.       
  377.     public static class ArraListFragment extends ListFragment{  
  378.         @Override  
  379.         public void onActivityCreated(Bundle savedInstanceState) {  
  380.             // TODO Auto-generated method stub  
  381.             super.onActivityCreated(savedInstanceState);  
  382.             String [] array = new String[]{"C""C++""Java"};  
  383.             setListAdapter(new ArrayAdapter<String>(getActivity(),   
  384.                     android.R.layout.simple_list_item_1, array));  
  385.         }  
  386.           
  387.         @Override  
  388.         public void onListItemClick(ListView l, View v, int position, long id) {  
  389.             // TODO Auto-generated method stub  
  390.             super.onListItemClick(l, v, position, id);  
  391.         }  
  392.     }  
  393.       
  394.     public static class CursorLoaderFragment extends ListFragment implements  
  395.             OnQueryTextListener, LoaderCallbacks<Cursor> {  
  396.   
  397.         SimpleCursorAdapter mAdapter;  
  398.         String mCurFilter;  
  399.   
  400.         final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {  
  401.                 Contacts._ID, Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS,  
  402.                 Contacts.CONTACT_PRESENCE, Contacts.PHOTO_ID,  
  403.                 Contacts.LOOKUP_KEY, };  
  404.   
  405.         @Override  
  406.         public void onActivityCreated(Bundle savedInstanceState) {  
  407.             // TODO Auto-generated method stub  
  408.             super.onActivityCreated(savedInstanceState);  
  409.   
  410.             setEmptyText("No phone numbers");  
  411.             setHasOptionsMenu(true);  
  412.   
  413.             mAdapter = new SimpleCursorAdapter(getActivity(),  
  414.                     android.R.layout.simple_list_item_2, nullnew String[] {  
  415.                             Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },  
  416.                     new int[] { android.R.id.text1, android.R.id.text2 }, 0);  
  417.             setListAdapter(mAdapter);  
  418.             setListShown(false);  
  419.             getLoaderManager().initLoader(0nullthis);  
  420.         }  
  421.   
  422. //      @Override  
  423. //      public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {  
  424. //          // TODO Auto-generated method stub  
  425. //          MenuItem item = menu.add("Search");  
  426. //          item.setIcon(android.R.drawable.ic_menu_search);  
  427. //          item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM  
  428. //                  | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);  
  429. //          SearchView sv = new SearchView(getActivity());  
  430. //          sv.setOnQueryTextListener(this);  
  431. //          item.setActionView(sv);  
  432. //      }  
  433.   
  434.         @Override  
  435.         public boolean onQueryTextChange(String newText) {  
  436.             // TODO Auto-generated method stub  
  437.             String newFilter = !TextUtils.isEmpty(newText) ? newText : null;  
  438.             if (mCurFilter == null && newFilter == null) {  
  439.                 return true;  
  440.             }  
  441.             if (mCurFilter != null && mCurFilter.equals(newFilter)) {  
  442.                 return true;  
  443.             }  
  444.   
  445.             mCurFilter = newFilter;  
  446.             getLoaderManager().restartLoader(0nullthis);  
  447.             return true;  
  448.         }  
  449.   
  450.         @Override  
  451.         public boolean onQueryTextSubmit(String query) {  
  452.             // TODO Auto-generated method stub  
  453.             return true;  
  454.         }  
  455.   
  456.         @Override  
  457.         public void onListItemClick(ListView l, View v, int position, long id) {  
  458.             // TODO Auto-generated method stub  
  459.             super.onListItemClick(l, v, position, id);  
  460.             Cursor c = (Cursor) mAdapter.getItem(position);  
  461.             String name = c.getString(0);  
  462.             Toast.makeText(getActivity(), "name:" + name, Toast.LENGTH_SHORT)  
  463.                     .show();  
  464.         }  
  465.   
  466.         @Override  
  467.         public Loader<Cursor> onCreateLoader(int id, Bundle args) {  
  468.             // TODO Auto-generated method stub  
  469.             Uri baseUri;  
  470.             if (mCurFilter != null) {  
  471.                 baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,  
  472.                         Uri.encode(mCurFilter));  
  473.             } else {  
  474.                 baseUri = Contacts.CONTENT_URI;  
  475.             }  
  476.             String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("  
  477.                     + Contacts.HAS_PHONE_NUMBER + "=1) AND ("  
  478.                     + Contacts.DISPLAY_NAME + " != '' ))";  
  479.             return new CursorLoader(getActivity(), baseUri,  
  480.                     CONTACTS_SUMMARY_PROJECTION, select, null,  
  481.                     Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");  
  482.         }  
  483.   
  484.         @Override  
  485.         public void onLoadFinished(Loader<Cursor> loader, Cursor data) {  
  486.             // TODO Auto-generated method stub  
  487.             mAdapter.swapCursor(data);  
  488.             if (isResumed()) {  
  489.                 setListShown(true);  
  490.             } else {  
  491.                 setListShownNoAnimation(true);  
  492.             }  
  493.         }  
  494.   
  495.         @Override  
  496.         public void onLoaderReset(Loader<Cursor> arg0) {  
  497.             // TODO Auto-generated method stub  
  498.             mAdapter.swapCursor(null);  
  499.         }  
  500.     }  
  501.       
  502.     public static class ContextMenuFragment extends Fragment{  
  503.         @Override  
  504.         public View onCreateView(LayoutInflater inflater, ViewGroup container,  
  505.                 Bundle savedInstanceState) {  
  506.             // TODO Auto-generated method stub  
  507.             View root = inflater.inflate(R.layout.fragment_context_menu, container, false);  
  508.             registerForContextMenu(root.findViewById(R.id.long_press));  
  509.             return root;  
  510.         }  
  511.           
  512.         @Override  
  513.         public void onCreateContextMenu(ContextMenu menu, View v,  
  514.                 ContextMenuInfo menuInfo) {  
  515.             // TODO Auto-generated method stub  
  516.             super.onCreateContextMenu(menu, v, menuInfo);  
  517.             menu.add(Menu.NONE, R.id.a_item, Menu.NONE, "Menu A");  
  518.             menu.add(Menu.NONE, R.id.b_item, Menu.NONE, "Menu B");  
  519.         }  
  520.           
  521.         @Override  
  522.         public boolean onContextItemSelected(MenuItem item) {  
  523.             // TODO Auto-generated method stub  
  524.             switch (item.getItemId()) {  
  525.             case R.id.a_item:  
  526.                 Toast.makeText(getActivity(), "a_item...", Toast.LENGTH_SHORT).show();  
  527.                 break;  
  528.             case R.id.b_item:  
  529.                 Toast.makeText(getActivity(), "b_item...", Toast.LENGTH_SHORT).show();  
  530.                 break;  
  531.             default:  
  532.                 break;  
  533.             }  
  534.             return super.onContextItemSelected(item);  
  535.         }  
  536.     }  
  537.       
  538. }  



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值