03.实例篇:微信主页面模仿——ActionBar和ViewPager的使用(下篇)

ActionBar 浮动,毛玻璃渐变效果(仿蝉游记) 最近看了一下蝉游记这款 app ,发现其中有很多界面还是非常漂亮的,这里截了几幅图,一起来欣赏一下。可以看到第一张图片实现了毛玻璃效果,而且向上滚动的时候毛玻璃效果越来越明显,我今天就是要模仿这个效果先看下我实现的效果图吧:效果跟蝉游记的基本一致,那么来看看是怎么实现的; 1、先来分析一下, a)首先的定一个透明的并且浮动的 ActionBar b)需要获取 ActionBar 的高度,这可以 阅读详情

第一部分:ActionBar重要知识点汇总

1.什么ActionBar

主要用于向用户当前Activity的标题、导航按钮或者其它动作,使用它,统一了样式和更好适应不同的屏幕;
ActionBar 在Android3.0 API 11开始使用,通过Support Library在2.1(API 7)版本及其以上可以使用;
如果仅支持3.0以上设备,导入 import android.app.ActionBar
支持2.1以上的 , import android.support.v7.app.ActionBar

public abstract class ActionBar extends Object : android.app.ActionBar抽象类,不是视图view

2.给Activity添加ActionBar

    两点操作:
    Activity继承ActionBarActivity
    同时,Activity主题设置为 <activity   android:theme = "@style/Theme.AppCompat.Light"  ...  >(该主题的子类也可以)

3.动态移除ActionBar

    //API 11以上, getActionBar即可
    ActionBar actionBar = getSupportActionBar();
    actionBar.hide();
    
    actionBar.show(); //显示
    
    注意:动态移除或显示,会引发重新布局,如果不需要该操作,可以考虑overlay mode
    设置:windowActionBarOverlay=true

4.ActionBar选项菜单

   ActionBar上面有各种图标和文字按钮,还有个 overflow Button(不够空间或者不重要的,收缩)
   Activity通过onCreateOptionsMenu()方法填充ActionBar的Items;
    
   logo代替icon:默认显示icon,在<application>和<activity>的logo属性设置
    
   在menu res定义所有的Action Items;
    res/menu/main_activity_actions.xml
  <menu xmlns:android="http://schemas.android.com/apk/res/android" >
   
<item android:id="@+id/action_search"
         
android:icon="@drawable/ic_action_search"
         
android:title="@string/action_search"/>
   
<item android:id="@+id/action_compose"
         
android:icon="@drawable/ic_action_compose"
         
android:title="@string/action_compose" />
  </menu>  
    
    @Override
  public boolean onCreateOptionsMenu(Menu menu) {
   
// Inflate the menu items for use in the action bar
   
MenuInflater inflater = getMenuInflater();
    inflater
.inflate(R.menu.main_activity_actions, menu);
   
return super.onCreateOptionsMenu(menu);
  }  

    yourapp:名字自己起的,因为是支持库,系统没有内置showAsAction属性,所以需要自定义空间
    showAsAction:  ifRoom如果有空间,就直接显示在ActionBar上,没有空间,就收缩起来    
     <menu   xmlns:android = "http://schemas.android.com/apk/res/android"       
         xmlns:yourapp="http://schemas.android.com/apk/res-auto"   >
    <item android:id="@+id/action_search"
         
android:icon="@drawable/ic_action_search"
         
android:title="@string/action_search"
         
yourapp:showAsAction="ifRoom"  />
    ...
</menu>
  如果有空间同时显示文字:
  <item yourapp:showAsAction="ifRoom|withText" ... />
    如果想让某个Item一直出现ActionButton,设置为 always, 尽量不用该选项,避免狭窄屏幕问题
    
    Action Item事件:
    Activity首先处理ItemSelected事件,Fragment在后面;
    当Activity不做处理时,应该调用super,以让其他Fragment有机会处理,而不是仅仅返回false
     @Override
    public boolean onOptionsItemSelected(MenuItem item) {
   
// Handle presses on the action bar items
   
switch (item.getItemId()) {
       
case R.id.action_search:
            openSearch
();
           
return true;
       
case R.id.action_compose:
            composeMessage
();
           
return true;
       
default:
           
return super.onOptionsItemSelected(item);
   
}
}

5.使用分割的ActionBar

当手机屏幕狭窄时,在屏幕底部提供单独的bar,显示所有的Action Items
<application> <activity> 中设置 uiOptions="splitActionBarWhenNarrow"
支持老版本,使用<meta-data>
<manifest ...>
   
<activity uiOptions="splitActionBarWhenNarrow" ... >
       
<meta-data android:name="android.support.UI_OPTIONS"
                   
android:value="splitActionBarWhenNarrow" />
   
</activity>
</manifest>
通过设置,允许收缩Action Bar(顶部的)
setDisplayShowHomeEnabled(false) and setDisplayShowTitleEnabled(false).

6.向前返回 导航

  Up导航不同于Back,Back由系统按照screen历史记录,up根据应用的层次结构设置;
   (1)让app icon成为Up Button,设置
   ActionBar actionBar = getSupportActionBar();
 actionBar.setDisplayHomeAsUpEnabled(true);
 (2)定义Up Parent Activity:两种方式
  <activity
        android:name="com.example.myfirstapp.DisplayMessageActivity"
       
android:label="@string/title_activity_display_message"
       
android:parentActivityName="com.example.myfirstapp.MainActivity" >
       
<!-- Parent activity meta-data to support API level 7+ -->
       
<meta-data
           
android:name="android.support.PARENT_ACTIVITY"
           
android:value="com.example.myfirstapp.MainActivity" />
 
</activity>
    
   或者重写,适合每个页面返回不一样的Activity
    getSupportParentActivityIntent() 
    onCreateSupportNavigateUpTaskStack()
   

7.添加Action View: Action Button的替代:一定注意使用yourapp,否则低版本的应用无法显示;

   通过actionLayout或者actionViewClass定义
   添加一个搜索框
     <? xml version = "1.0"  encoding = "utf-8" ?>
  <menu xmlns:android="http://schemas.android.com/apk/res/android"
     
xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
   
<item android:id="@+id/action_search"
         
android:title="@string/action_search"
         
android:icon="@drawable/ic_action_search"
         
yourapp:showAsAction="ifRoom|collapseActionView"
         
yourapp:actionViewClass="android.support.v7.widget.SearchView" />
</menu>
  注意:collapseActionView 必须添加,说明该view被收缩
  获取ActionView:
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater
().inflate(R.menu.main_activity_actions, menu);
   
MenuItem searchItem = menu.findItem(R.id.action_search);
   
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
   
// Configure the search info and add any event listeners
   
...
   
return super.onCreateOptionsMenu(menu);
}
  处理收缩的Action View:
  @Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater
().inflate(R.menu.options, menu);
   
MenuItem menuItem = menu.findItem(R.id.actionItem);
   
...

   
// When using the support library, the setOnActionExpandListener() method is
   
// static and accepts the MenuItem object as an argument
   
MenuItemCompat.setOnActionExpandListener(menuItem, new OnActionExpandListener() {
       
@Override
       
public boolean onMenuItemActionCollapse(MenuItem item) {
           
// Do something when collapsed
           
return true;  // Return true to collapse action view
       
}

       
@Override
       
public boolean onMenuItemActionExpand(MenuItem item) {
           
// Do something when expanded
           
return true;  // Return true to expand action view
       
}
   
});
}

8.添加 Action Provider

   和Action View类似,但是可以完全控制Action的行为,可以定义每个按钮的子菜单
   使用内置的ActionProvider或者继承ActionProvider
   每个ActionProvider,可以定义自己的行为,无须在Activity中定义onOptionsItemsSelected,如果定义,不要返回true,返回false,以便于其它ActionProvider处理;
   <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
     
xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
   
<item android:id="@+id/action_share"
         
android:title="@string/share"
         
yourapp:showAsAction="ifRoom"
         
yourapp:actionProviderClass="android.support.v7.widget.ShareActionProvider"
         
/>
    ...
</menu>
private ShareActionProvider mShareActionProvider;

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater
().inflate(R.menu.main_activity_actions, menu);

   
// Set up ShareActionProvider's default share intent
   
MenuItem shareItem = menu.findItem(R.id.action_share);
    mShareActionProvider
= (ShareActionProvider)
           
MenuItemCompat.getActionProvider(shareItem);
    mShareActionProvider
.setShareIntent(getDefaultIntent());

   
return super.onCreateOptionsMenu(menu);
}

/** Defines a default (dummy) share intent to initialize the action provider.
  * However, as soon as the actual content to be used in the intent
  * is known or changes, you must update the share intent by again calling
  * mShareActionProvider.setShareIntent()
  */
private Intent getDefaultIntent() {
   
Intent intent = new Intent(Intent.ACTION_SEND);
    intent
.setType("image/*");
   
return intent;
}

9.创建定制的ActionProvider

  方便重用和管理ActionItem的行为,不需要在Fragment或者Activity中处理;
    继承ActionProvider,实现回调方法即可:
    ActionProvider(Context context): 构造器,会传递一个context,可以保存到一个字段中,方便使用
    onCreateActionView(MenuItem): 对于每一个的MenuItem,创建ActionView
    public View onCreateActionView(MenuItem forItem) {
    // Inflate the action view to be shown on the action bar.
   
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
   
View view = layoutInflater.inflate(R.layout.action_provider, null);
   
ImageButton button = (ImageButton) view.findViewById(R.id.button);
    button
.setOnClickListener(new View.OnClickListener() {
       
@Override
       
public void onClick(View v) {
           
// Do something...
       
}
   
});
   
return view;
}
    onPerformDefaultAction():当action overflow的菜单项被选择,调用执行默认的Action
     如果Action View有子菜单,onPrepareSubMenu()调用,不会调用该方法;
     如果在Activity或者Fragment中已经处理 onOptionsItemSelected() (返回true的话),也不会调用;

10.添加导航的Tab

    布局中必须有一个Id的ViewGroup,绑定Fragment和Tab
    如果每个Tab内容填充整个屏幕,可以使用内置的布局,通过android.R.id.content 引用
    基本过程:
    实现ActionBar.TabListener接口,响应用户点击切换tab事件;【滑动切换,用ViewPager】
    动态添加每个Tab: 初始化ActionBar.Tab, setTabListener, setText,setIcon,addTab
     getSelectedNavigationIndex():获取tab索引位置
    注意:系统调用commit,自己不用调用,调用将失败;不能够将tab压入stack中
    public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
    private Fragment mFragment;
   
private final Activity mActivity;
   
private final String mTag;
   
private final Class<T> mClass;

   
/** Constructor used each time a new tab is created.
      * @param activity  The host Activity, used to instantiate the fragment
      * @param tag  The identifier tag for the fragment
      * @param clz  The fragment's Class, used to instantiate the fragment
      */
   
public TabListener(Activity activity, String tag, Class<T> clz) {
        mActivity
= activity;
        mTag
= tag;
        mClass
= clz;
   
}

   
/* The following are each of the ActionBar.TabListener callbacks */

   
public void onTabSelected(Tab tab, FragmentTransaction ft) {
       
// Check if the fragment is already initialized
       
if (mFragment == null) {
           
// If not, instantiate and add it to the activity
            mFragment
= Fragment.instantiate(mActivity, mClass.getName());
            ft
.add(android.R.id.content, mFragment, mTag);
       
} else {
           
// If it exists, simply attach it in order to show it
            ft
.attach(mFragment);
       
}
   
}

   
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
       
if (mFragment != null) {
           
// Detach the fragment, because another one is being attached
            ft
.detach(mFragment);
       
}
   
}

   
public void onTabReselected(Tab tab, FragmentTransaction ft) {
       
// User selected the already selected tab. Usually do nothing.
   
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
   
super.onCreate(savedInstanceState);
   
// Notice that setContentView() is not used, because we use the root
   
// android.R.id.content as the container for each fragment

   
// setup action bar for tabs
   
ActionBar actionBar = getSupportActionBar();
    actionBar
.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    actionBar
.setDisplayShowTitleEnabled(false);

   
Tab tab = actionBar.newTab()
                       
.setText(R.string.artist)
                       
.setTabListener(new TabListener<ArtistFragment>(
                               
this, "artist", ArtistFragment.class));
    actionBar
.addTab(tab);

    tab
= actionBar.newTab()
                   
.setText(R.string.album)
                   
.setTabListener(new TabListener<AlbumFragment>(
                           
this, "album", AlbumFragment.class));
    actionBar
.addTab(tab);
}

11.添加下拉列表式导航

     当导航的内容不是经常切换的时候,使用下拉列表式(spinner),如果内容经常切换,使用tab
     创建下拉列表的基本过程:
 
  • SpinnerAdapter:提供数据项和布局视图
  • 实现ActionBar.onNavigationListener接口,监听列表项选择事件
  • 在Activity的onCreate方法,设置ActionBar的mode,setNavigationMode(NAVIGATION_MODE_LIST).
  • actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback);
  • SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this,
            R
    .array.action_list, android.R.layout.simple_spinner_dropdown_item);
    mOnNavigationListener = new OnNavigationListener() {
     
    // Get the same strings provided for the drop-down's ArrayAdapter
     
    String[] strings = getResources().getStringArray(R.array.action_list);

     
    @Override
     
    public boolean onNavigationItemSelected(int position, long itemId) {
       
    // Create new fragment from our own Fragment class
       
    ListContentFragment newFragment = new ListContentFragment();
       
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();

       
    // Replace whatever is in the fragment container with this fragment
       
    // and give the fragment a tag name equal to the string at the position
       
    // selected
        ft
    .replace(R.id.fragment_container, newFragment, strings[position]);

       
    // Apply changes
        ft
    .commit();
       
    return true;
     
    }
    };
    public class ListContentFragment extends Fragment {
       
    private String mText;

       
    @Override
       
    public void onAttach(Activity activity) {
         
    // This is the first callback received; here we can set the text for
         
    // the fragment as defined by the tag specified during the fragment
         
    // transaction
         
    super.onAttach(activity);
          mText
    = getTag();
       
    }

       
    @Override
       
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
               
    Bundle savedInstanceState) {
           
    // This is called to define the layout for the fragment;
           
    // we just create a TextView and set its text to be the fragment tag
           
    TextView text = new TextView(getActivity());
            text
    .setText(mText);
           
    return text;
       
    }
    }

第二部分:ViewPager组件的使用

1.public class ViewPager extends android.view.ViewGroup 

   android.support.v4.view.ViewPager
   布局管理器,实现通过滑动切换页面,提供接口PagerAdapter的实现产生Page
   ViewPager经常与Fragment联合使用,并提供标准的Adapter:FragmentPagerAdapter和FragmentStatePagerAdapter

2.public abstract class PagerAdapter  extends Object  [android.support.v4.view.PagerAdapter]

   抽象类,提供基本接口,产生ViewPager需要的page,子类必须实现抽象方法或者重写:
   Object instantiateItem(ViewGroup container, int position):创建给定位置的视图Page
   void destroyItem(ViewGroup container, int position, Object object):移除给定位置的Page
   abstract boolean isViewFromObject(View view, Object object):判断Page和返回的对象是否相等,return view == object
   abstract int getCount():返回可用的Pager数目
    
   ViewPager关联Page到一个Object,而不是视图View,调用的过程:
   startUpdate(ViewGroup):表明即将开始更新页面
   instantiateItem(ViewGroup, int) and/or destroyItem(ViewGroup, int, Object):多次调用
   finishUpdate(ViewGroup):结束更新,返回对象;
   每当Adapter发生改变,应该 notifyDataSetChanged() ,通知更新;

    两个直接抽象子类:FragmentPagerAdapter和FragmentStatePagerAdapter
    FragmentPagerAdapter:实现了PagerAdapter,并且返回的每个Page是Fragment,适合静态的一定量的页面,对于大量的页面集合,使用FragmentStatePagerAdapter
   只需要实现的getItem(int)和getCount()方法接口,同时ViewPager必须有一个有效的Id
   FragmentStatePagerAdapter:返回Fragment,同时处理保存和恢复Fragment的状态,适合保存大量的Page,工作方式类似于ListView,当Fragment不可见,将可能完全销毁,仅仅保存状态,相对于前面的Adapter,使用更少的内存;
   实例代码:
  •     public class FragmentPagerSupport extends FragmentActivity {
        static final int NUM_ITEMS = 10;

       
    MyAdapter mAdapter;

       
    ViewPager mPager;

       
    @Override
       
    protected void onCreate(Bundle savedInstanceState) {
           
    super.onCreate(savedInstanceState);
            setContentView
    (R.layout.fragment_pager);

            mAdapter
    = new MyAdapter(getSupportFragmentManager());

            mPager
    = (ViewPager)findViewById(R.id.pager);
            mPager
    .setAdapter(mAdapter);

           
    // Watch for button clicks.
           
    Button button = (Button)findViewById(R.id.goto_first);
            button
    .setOnClickListener(new OnClickListener() {
               
    public void onClick(View v) {
                    mPager
    .setCurrentItem(0);
               
    }
           
    });
            button
    = (Button)findViewById(R.id.goto_last);
            button
    .setOnClickListener(new OnClickListener() {
               
    public void onClick(View v) {
                    mPager
    .setCurrentItem(NUM_ITEMS-1);
               
    }
           
    });
       
    }

       
    public static class MyAdapter extends FragmentPagerAdapter {
           
    public MyAdapter(FragmentManager fm) {
               
    super(fm);
           
    }

           
    @Override
           
    public int getCount() {
               
    return NUM_ITEMS;
           
    }

           
    @Override
           
    public Fragment getItem(int position) {
               
    return ArrayListFragment.newInstance(position);
           
    }
       
    }

       
    public static class ArrayListFragment extends ListFragment {
           
    int mNum;

           
    /**
             * Create a new instance of CountingFragment, providing "num"
             * as an argument.
             */
           
    static ArrayListFragment newInstance(int num) {
               
    ArrayListFragment f = new ArrayListFragment();

               
    // Supply num input as an argument.
               
    Bundle args = new Bundle();
                args
    .putInt("num", num);
                f
    .setArguments(args);

               
    return f;
           
    }

           
    /**
             * When creating, retrieve this instance's number from its arguments.
             */
           
    @Override
           
    public void onCreate(Bundle savedInstanceState) {
               
    super.onCreate(savedInstanceState);
                mNum
    = getArguments() != null ? getArguments().getInt("num") : 1;
           
    }

           
    /**
             * The Fragment's UI is just a simple text view showing its
             * instance number.
             */
           
    @Override
           
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                   
    Bundle savedInstanceState) {
               
    View v = inflater.inflate(R.layout.fragment_pager_list, container, false);
               
    View tv = v.findViewById(R.id.text);
               
    ((TextView)tv).setText("Fragment #" + mNum);
               
    return v;
           
    }

           
    @Override
           
    public void onActivityCreated(Bundle savedInstanceState) {
               
    super.onActivityCreated(savedInstanceState);
                setListAdapter
    (new ArrayAdapter<String>(getActivity(),
                        android
    .R.layout.simple_list_item_1, Cheeses.sCheeseStrings));
           
    }

           
    @Override
           
    public void onListItemClick(ListView l, View v, int position, long id) {
               
    Log.i("FragmentList", "Item clicked: " + id);
           
    }
       
    }
    }

    The R.layout.fragment_pager resource of the top-level fragment is:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
           
    android:orientation="vertical" android:padding="4dip"
           
    android:gravity="center_horizontal"
           
    android:layout_width="match_parent" android:layout_height="match_parent">

       
    <android.support.v4.view.ViewPager
               
    android:id="@+id/pager"
               
    android:layout_width="match_parent"
               
    android:layout_height="0px"
               
    android:layout_weight="1">
       
    </android.support.v4.view.ViewPager>

       
    <LinearLayout android:orientation="horizontal"
               
    android:gravity="center" android:measureWithLargestChild="true"
               
    android:layout_width="match_parent" android:layout_height="wrap_content"
               
    android:layout_weight="0">
           
    <Button android:id="@+id/goto_first"
               
    android:layout_width="wrap_content" android:layout_height="wrap_content"
               
    android:text="@string/first">
           
    </Button>
           
    <Button android:id="@+id/goto_last"
               
    android:layout_width="wrap_content" android:layout_height="wrap_content"
               
    android:text="@string/last">
           
    </Button>
       
    </LinearLayout>
    </LinearLayout>

    The R.layout.fragment_pager_list resource containing each individual fragment's layout is:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       
    android:orientation="vertical"
       
    android:layout_width="match_parent"
       
    android:layout_height="match_parent"
       
    android:background="@android:drawable/gallery_thumb">

       
    <TextView android:id="@+id/text"
           
    android:layout_width="match_parent" android:layout_height="wrap_content"
           
    android:gravity="center_vertical|center_horizontal"
           
    android:textAppearance="?android:attr/textAppearanceMedium"
           
    android:text="@string/hello_world"/>

       
    <!-- The frame layout is here since we will be showing either
        the empty view or the list view.  -->
       
    <FrameLayout
           
    android:layout_width="match_parent"
           
    android:layout_height="0dip"
           
    android:layout_weight="1" >
           
    <!-- Here is the list. Since we are using a ListActivity, we
                 have to call it "@android:id/list" so ListActivity will
                 find it -->
           
    <ListView android:id="@android:id/list"
               
    android:layout_width="match_parent"
               
    android:layout_height="match_parent"
               
    android:drawSelectorOnTop="false"/>

           
    <!-- Here is the view to show if the list is emtpy -->
           
    <TextView android:id="@android:id/empty"
               
    android:layout_width="match_parent"
               
    android:layout_height="match_parent"
               
    android:textAppearance="?android:attr/textAppearanceMedium"
               
    android:text="No items."/>

       
    </FrameLayout>

    </LinearLayout>
    

3.使用方法,经常与Tab ActionBar结合,支持点击和滑动换页,具体见 csdn博客android微信实例开发

   使用要点: 【关键是Tab点击事件和ViewPager滑动选择事件联合起来】
   XML或代码定义ViewPager,但是必须设置有效的id;
    
   设置ActionBar的tab导航模式;
   实现ActionBar.TabListener:选择事件改变当前的ViewPager的页面  
    
   实现FragmentPagerAdapter,和Fragment对象;
   实现ViewPager.OnPagerChangeListener:滑动事件改变当前的ViewPager页面和Tab选择情况
    
   public static interface  ActionBar.TabListener
           abstract void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft)
           abstract void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft)
           abstract void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft)
   
 public static interface ViewPager.OnPageChangeListener:
            abstract void onPageScrollStateChanged(int state) :
                   当scroll滚动的状态发生改变时,可以发现用户什么时候开始拖动、正在拖动设置中、以及完成拖动设置好页面;
                   三种状态:SCROLL_STATE_IDLE(0)、SCROLL_STATE_DRAGGING(1) 、SCROLL_STATE_SETTLING(2)
            public abstract void onPageScrolled (int position, float positionOffset, int positionOffsetPixels):
                   当前的页面被拖动时调用,position当前拖动的页面index,offset不为0,则position+1可见,取值范围[0,1)
            
            public abstract void onPageSelected (int position):
                   当一个新的已经被选择后,调用(动画不必完成)    

            刚刚启动ViewPager时,会调用一次onPageScrolled方法,当滑动切换时,上述三个方法的调用顺序是:
开始点击滑动时,调用onPageScrollStateChanged一次(此时状态为SCROLL_STATE_DRAGGING),然后一直调用onPageScrolled计算滑动的位置(多次调用),当你放手,结束滑动,调用onPageScrollStateChanged一次(此时状态为SCROLL_STATE_SETTLING),然后调用onPageSelected一次(确定选中的Page),接着还要调用onPageScrolled多次,滑动到指定的Page,然后再次调用onPageScrollStateChanged一次(此时状态为SCROLL_STATE_IDLE),具体见图,当滑动“聊天”到“发现”页面时,截图;


Android制作微信app顶部menu菜单(ActionBar) 主要为大家详细介绍了Android利用ActionBar制作微信app顶部menu菜单,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 立即下载

相关推荐

使用VLC库实现视频播放器(WPF版)

使用wpf制作一个视频播放器 一、 LibVLCSharp介绍 LibVLCSharp是基于VideoLAN的LibVLC库的.NET平台的跨平台音频和视频API。它提供了一个全面的多媒体API,可以跨移动、服务器和桌面使用,以呈现视频和输出音频。支持Mono、.NET Framework和.NET核心运行时。在vs工具中,只需要安装截图中得两个nuget包。 二、视频播放器的实现 视频播放器的实现需要用到两个比较nuget包中提供的类,MediaPlayer类。MediaPlayer类型用于控

cangqiongxiaoye的博客 1万+

微信6.0 ActionBar样式

微信6.0的ActionBar比较简洁只有一个搜索框和一个溢出(overflow)菜单。这个溢出菜单可以看到不是默认的,而是一个“+”号图标。 并且溢出菜单中点击,里面的隐藏菜单图标可以显示出来。(系统默认是不显示的) 文章主要分三部分: 一.主要介绍:如何高仿微信6.0ActionBar; 1.溢出菜单不显示 2.自定义溢出菜单的图标样式 3.隐藏图标的显示。 二.取巧的方法;

蝌蚪鱼 1694

Android ActionBar应用实战,高仿微信主界面的设计

相信大家都会认定微信是在手机上最火的应用程序了,几乎每个人的手机上都有安装它。微信除了功能非常强大之外,界面也是做得相当美观,它的ActionBar让人看着有一种赏心悦目的感觉。作为手机应用程序中的技术标杆,我们自然应该多多向微信学习,那么今天实战的主题,就是模仿微信主界面的实现。 首先新建一个Android项目,起名叫作WeChatSample。既然是要实现ActionBar,那么第一步当然就是编辑menu目录下的main.xml文件了,代码如下所示

郭霖的专栏 9万+

无法找到来自源 nvlddmkm 的事件 ID 14 的描述

具体错误是: 无法找到来自源 nvlddmkm 的事件 ID 14 的描述。本地计算机上未安装引发此事件的组件,或者安装已损坏。可以安装或修复本地计算机上的组件。 出现这样错误的原因有很多了,有可能是硬件有可能是软件。由于我是刚配置的电脑,起初非常怀疑是自己组装的问题,折腾了好久,心态爆炸!!!先说我报这样错误的情况,以及解决办法,供后面人参考。 ...

SeventhBlue 6万+

YOLOv11+SAHI实战:5步搞定无人机航拍小目标检测(附VisDrone数据集调参技巧)

本文详细介绍了如何结合YOLOv11目标检测框架与SAHI切片推理技术,高效解决无人机航拍图像中的小目标检测难题。通过VisDrone数据集调参技巧和5步实战指南,帮助开发者快速构建高性能检测系统,显著提升小目标检测的准确率和效率。

rum55的博客 190

V7 Actionbar 仿微信首页的头部效果

在尝试做Actionbar时遇到了以下问题: 1、自定义的Actionbar的 overflow 点击时不弹出任何东西(点击“+”号 2、弹出的overflow 盖住了部分 action 3、自定义Actionbar的各个menu的背景颜色及字体颜色。

sinat_29398599的博客 1058

IntelliJ IDEA 中git使用说明书

IntelliJ IDEA 中git使用说明书

junyang2012的博客 5388

android ActionBar的使用(模仿微信界面)

修改menu 文件下的main.xml <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:context="com.ll.testactionbar.MainActivity" > <item

u010992774的博客 521

告别手动打点!用Cesium为你的大疆无人机快速生成区域巡查航线(保姆级教程)

本文详细介绍了如何利用Cesium平台为大疆无人机快速生成区域巡查航线的保姆级教程。通过自动化航线规划,告别传统手动打点的繁琐操作,实现高效、无死角的区域覆盖。文章涵盖环境搭建、实战案例及高级优化技巧,特别适合无人机操作员和巡检工作者提升工作效率。

weixin_30399821的博客 518

Android功耗系列专题理论之十三:MTK平台待机功耗问题分析方法

摘要:本文详细分析了MTK平台待机功耗问题的调试方法,重点介绍了SPM电源管理机制、26M时钟控制逻辑以及系统深睡眠状态的判断标准。文章提供了完整的Debug流程,包括日志抓取、唤醒源分析、SCP睡眠状态检查以及时钟/LDO状态排查等实用技巧,并给出硬件漏电点和软件配置异常的排查方案。针对不同模块(Modem/Conn/SSPM等)提供了具体的电源管理绕过命令,适用于功耗问题调试和低功耗模式验证场景。

559

如何使用ActionBar+ViewPager实现fragment相互切换

本篇博客主要介绍如何使用ActionBar,并将ActionBar的导航模式设置tab模式,之所以了解到这种用法还是因为看了手机桌面时钟的源码。感觉这种方法很cool,不过已经被google废弃了,现在就做为了解一下吧!!先看一下效果图吧

朱玉强的博客 620

Python爬虫实战:美团外卖商家数据抓取与分析

随着互联网技术的快速发展,外卖平台已成为人们日常生活中不可或缺的一部分。本文基于Python爬虫技术,使用最新的异步爬虫框架和反爬虫绕过技术,实现了对美团外卖平台商家信息与评分数据的自动化抓取。通过对抓取数据的清洗、存储和分析,为餐饮行业市场研究和商业决策提供数据支持。本文详细介绍了爬虫的设计思路、技术实现方案、数据处理方法以及可视化分析结果,为相关领域的研究者和开发者提供参考。关键词:Python爬虫;美团外卖;数据抓取;数据分析;异步爬虫。

2201_76125261的博客 1821

微信主界面开发知识点

微信主页面开发weixin6.0版主要功能点: 实现ActionBar:利用到反射知识,替换默认的overflowButton 实现viewPager 实现底部的tab:利用到自定义view的知识 Activity回收 大概开发步骤思维导图: 1、实现ActionBar java反射机制,可以查看http://www.cnblogs.com/octobershiner/archive/2012/0

一枚疯女纸 737

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

【android开发资源 汇总贴】关于微信的那点帖。

按照惯例发帖先吐槽一下:最近看到大家发防微信功能特别的多,所以就汇总了一下,看看大家还有什么其他方面的汇总需求,回复我噢,均可满足。。。。。 (ps:有些帖子由于主观、客观还有神马原因,没有发现,如果大家发现了可以回复我,我随时放上去) [Android实例 仿微信侧滑删除SwipeListView实例 2014/08/14 http://www.eoeandroid.

大神了没 902

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

02.实例篇:微信主页面模仿——ActionBar的应用(上篇)

一.写在前面 什么是ActionBar,ActionBar的作用,ActionBar其实就是页面上方的"工具栏"。在说明理论知识之前,先来看个例子吧,本例子主要是模仿实现微信Android5.2.1的主页面的实现。 二.界面特点分析: 页面上部是一个带标签(Tab)的ActionBar,ActionBar上面左边是Logo,右边是三个ActionView 按钮(依次是SeacherV

壹零Boy-MePlusPlus(米加加)的博客 1794

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Android25_ActionBar

一、ActionBar:(动作栏) (一)、简介:(扩展TitleBar)         Action bar(动作栏)是一个导航控件,用以代替传统屏幕顶端的标题栏。ActionBar显示在屏幕顶部的控件,它包括了在左边显示的应用的logo图标和右边操作菜单的可见项。类似于windows桌面程序的工具栏。 效果如下图: 1、ActionBar主要功能:   

雷家二少 634

【Android UI设计与开发】8.顶部标题栏(一)ActionBar 奥义·详解

一、ActionBar介绍   在Android 3.0中除了我们重点讲解的Fragment外,Action Bar也是一个非常重要的交互元素,Action Bar取代了传统的tittle bar和menu,在程序运行中一直置于顶部,对于Android平板设备来说屏幕更大它的标题使用Action Bar来设计可以展示更多丰富的内容,方便操控。 二、ActionBar的功能  ...

2832

仿微信效果,主要是actionbar的一些知识

仿微信效果,主要是actionbar的一些知识

pangzaifei的专栏 2982

什么是ActionBar,详细讲解

更详细讲解https://blog.csdn.net/b1480521874/article/details/90812777 一、什么是ActionBar 有图有真相,看一下图片就了解的差不多了 对于大多数应用,操作栏可以分割为 4 个不同的功能区域。  <1> 应用图标 ActionBar的图标,可显示软件图标,也可用其他图标代替。当软件不在最高级页面时,图标左侧会显示一个左箭头,用户可以通过这个箭头向上导航;  <2>视图控制 如果你的应...

qq_40638618的博客 5789

仿微信,学Android:ActionBar 制作

Android学习:仿微信系列:ActionBar制作 柯振旭 2015 年3月30日 1 效果展示 以下就是我们今天要实现的效果图: 2 实现难点2.1隐藏ActionBar标题栏旁边的应用Logo 在经典的Android应用中,顶部ActionBa...

keZhenxu 194

微信小程序 底部导航tobBar实现 和 界面顶部显示

文章目录微信小程序 底部导航topBar实现效果图展示代码:属性解释微信小程序 界面顶部显示效果图代码实现属性解释 微信小程序 底部导航topBar实现 效果图展示 代码: app.jaon { "pages": [ "pages/index/index", "pages/logs/logs", "pages/second/second", "pages/...

小胖_@的博客 2726

高仿微信APP实战(一)-Actionbar的制作与应用

高仿微信APP实战(一)-Actionbar的制作与应用本文是仿微信app实战系列的第一部分,先从简单的做起,边做边学习。从顶部actionbar开始,先看一下效果图: 一、定义主题样式<resources> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="col

baidu_20535887的博客 1316

漂亮的ActionBar效果

Newsstand—这个应用引进了新的方式,使得ActionBar达到了新的水平。如果你打开这个应用的发布页,你会注意到不带图标的ActionBar是半透明的,而且和一个大的图片集(一个大的杂志图标,描述了一些新闻)交叠在一起。一旦你开始下滑,大杂志图标会位移并缩放,以匹配ActionBar的图标所在。 这样做的主要优势是使ActionBar真正成为内容的一部分。 在这篇文章中,我主要解释...

weixin_34075268的博客 145
上一篇: 02.实例篇:微信主页面模仿——ActionBar的应用(上篇)
下一篇: 04.基础篇:Ubuntu12.04下搭建最新Android开发环境问题
壹零Boy
博客等级 码龄14年 31粉丝 43原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值