• Android 之高仿微信主界面


    源码下载:  https://files.cnblogs.com/aibuli/WeChatSample.zip

    主界面主要使用ActionBar来完成.  要实现这个效果,第一步当然是编辑menu目录下的main.xml文件.
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        tools:context="com.example.wechatsample.MainActivity" >
     
        <item
            android:id="@+id/action_search"
            android:actionViewClass="android.widget.SearchView"
            android:icon="@drawable/actionbar_search_icon"
            android:showAsAction="ifRoom|collapseActionView"
            android:title="@string/action_search"/>
        <item
            android:id="@+id/action_plus"
            android:actionProviderClass="com.example.wechatsample.PlusActionProvider"
            android:icon="@drawable/actionbar_add_icon"
            android:showAsAction="ifRoom"
            android:title="@string/action_plus"/>
        <item
            android:id="@+id/action_album"
            android:icon="@drawable/ofm_photo_icon"
            android:title="@string/action_album"/>
        <item
            android:id="@+id/action_collection"
            android:icon="@drawable/ofm_collect_icon"
            android:title="@string/action_collection"/>
        <item
            android:id="@+id/action_card"
            android:icon="@drawable/ofm_card_icon"
            android:title="@string/action_card"/>
        <item
            android:id="@+id/action_settings"
            android:icon="@drawable/ofm_setting_icon"
            android:title="@string/action_settings"/>
        <item
            android:id="@+id/action_feed"
            android:icon="@drawable/ofm_feedback_icon"
            android:title="@string/action_feed"/>
     
    </menu> 
     
    在上面的main.xml中,有一个自定义Action Provider  , 叫做 PlusActionProvider, 这主要用于模仿微信中那个加号的子菜单的.
     
    public class PlusActionProvider extends ActionProvider {
     
        private Context context;
     
        public PlusActionProvider(Context context) {
            super(context);
            this.context = context;
        }
     
        @Override
        public View onCreateActionView() {
            return null;
        }
     
        @Override
        public void onPrepareSubMenu(SubMenu subMenu) {
            subMenu.clear();
            subMenu.add(context.getString(R.string.plus_group_chat))
                    .setIcon(R.drawable.ofm_group_chat_icon)
                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem item) {
                            return true;
                        }
                    });
            subMenu.add(context.getString(R.string.plus_add_friend))
                    .setIcon(R.drawable.ofm_add_icon)
                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem item) {
                            return false;
                        }
                    });
            subMenu.add(context.getString(R.string.plus_video_chat))
                    .setIcon(R.drawable.ofm_video_icon)
                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem item) {
                            return false;
                        }
                    });
            subMenu.add(context.getString(R.string.plus_scan))
                    .setIcon(R.drawable.ofm_qrcode_icon)
                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem item) {
                            return false;
                        }
                    });
            subMenu.add(context.getString(R.string.plus_take_photo))
                    .setIcon(R.drawable.ofm_camera_icon)
                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem item) {
                            return false;
                        }
                    });
        }
     
        @Override
        public boolean hasSubMenu() {
            return true;
        }
     
    } 
    在PlusActionProvider中定义了五个子菜单, 每个子菜单都指定了一个标题和一个图标.
    虽然给每个子菜单都定义了点击事件,但都没具体进行实现.
    接着修改 MainActivity代码:
    public class MainActivity extends Activity {  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
            setOverflowShowingAlways();  
        }  
      
        @Override  
        public boolean onCreateOptionsMenu(Menu menu) {  
            getMenuInflater().inflate(R.menu.main, menu);  
            return true;  
        }  
      
        @Override  
        public boolean onMenuOpened(int featureId, Menu menu) {  
            if (featureId == Window.FEATURE_ACTION_BAR && menu != null) {  
                if (menu.getClass().getSimpleName().equals("MenuBuilder")) {  
                    try {  
                        Method m = menu.getClass().getDeclaredMethod(  
                                "setOptionalIconsVisible", Boolean.TYPE);  
                        m.setAccessible(true);  
                        m.invoke(menu, true);  
                    } catch (Exception e) {  
                    }  
                }  
            }  
            return super.onMenuOpened(featureId, menu);  
        }  
      
        private void setOverflowShowingAlways() {  
            try {  
                ViewConfiguration config = ViewConfiguration.get(this);  
                Field menuKeyField = ViewConfiguration.class  
                        .getDeclaredField("sHasPermanentMenuKey");  
                menuKeyField.setAccessible(true);  
                menuKeyField.setBoolean(config, false);  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
      
    }   
    在这里,onCreateOptionMenu()方法去加载main.xml文件,onMenuOpen()方法用于让隐藏在overflow当中的Action按钮显示出来,而setOverflowShowingAlways()方法则是屏蔽掉有物理Menu键,不然在有物理Menu键的手机上,overflow显示不出来.
     
    现在,界面已经基本成型,但是运行却发现,效果还是差很远.因为在字体颜色和大小还没有进行调整.因此还要自定义ActionBar的样子.
    <resources xmlns:android="http://schemas.android.com/apk/res/android">
     
        <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
            <item name="android:actionBarStyle">@style/WeChatActionBar</item>
            <item name="android:itemBackground">@drawable/actionbar_bg_selector</item>
            <item name="android:actionBarItemBackground">@drawable/actionbar_bg_selector</item>
            <item name="android:itemTextAppearance">@style/WeChatActionBarOverflow</item>
            <item name="android:actionOverflowButtonStyle">@style/WeChatActionButtonOverflow</item>
        </style>
     
        <style name="WeChatActionBar" parent="@android:style/Widget.Holo.ActionBar">
            <item name="android:background">#303537</item>
            <item name="android:titleTextStyle">@style/WeChatActionBarTitleText</item>
        </style>
     
        <style name="WeChatActionBarTitleText" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
            <item name="android:textColor">#cfcfcf</item>
            <item name="android:textSize">17sp</item>
        </style>
     
        <style name="WeChatActionBarOverflow" parent="@android:style/Widget.ActionButton.Overflow">
            <item name="android:textSize">16sp</item>
        </style>
     
        <style name="WeChatActionButtonOverflow" parent="android:style/Widget.Holo.ActionButton.Overflow">
            <item name="android:src">@drawable/actionbar_more_icon</item>
        </style>
     
    </resources> 
    在这里,对ActionBar的背景色,标题文字颜色和大小,子菜单背景进行了调整.
    在<applicationi>标签中增加了一个logo属性,在<activity>标签中增加了一个icon属性。现在运行一下程序,效果如下图所示:
    接下来,还有三个Tab键.
    PagerSlidingTabStrip   是Git上的一个开源框架.使用如下:
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
     
        <com.astuetz.PagerSlidingTabStrip
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="40dp" />
     
        <android.support.v4.view.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tabs" />
     
    </RelativeLayout> 
    在Main.xml中,   可滑动的ViewPager在TabStrip的下面.
    接着创建三个Fragment,用于切换Tab起作用.   
    public class MainActivity extends FragmentActivity {
     
        /**
         * 聊天界面的Fragment
         */
        private ChatFragment chatFragment;
     
        /**
         * 发现界面的Fragment
         */
        private FoundFragment foundFragment;
     
        /**
         * 通讯录界面的Fragment
         */
        private ContactsFragment contactsFragment;
     
        /**
         * PagerSlidingTabStrip的实例
         */
        private PagerSlidingTabStrip tabs;
     
        /**
         * 获取当前屏幕的密度
         */
        private DisplayMetrics dm;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            setOverflowShowingAlways();
            dm = getResources().getDisplayMetrics();
            ViewPager pager = (ViewPager) findViewById(R.id.pager);
            tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
            pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
            tabs.setViewPager(pager);
            setTabsValue();
        }
     
        /**
         * 对PagerSlidingTabStrip的各项属性进行赋值。
         */
        private void setTabsValue() {
            // 设置Tab是自动填充满屏幕的
            tabs.setShouldExpand(true);
            // 设置Tab的分割线是透明的
            tabs.setDividerColor(Color.TRANSPARENT);
            // 设置Tab底部线的高度
            tabs.setUnderlineHeight((int) TypedValue.applyDimension(
                    TypedValue.COMPLEX_UNIT_DIP, 1, dm));
            // 设置Tab Indicator的高度
            tabs.setIndicatorHeight((int) TypedValue.applyDimension(
                    TypedValue.COMPLEX_UNIT_DIP, 4, dm));
            // 设置Tab标题文字的大小
            tabs.setTextSize((int) TypedValue.applyDimension(
                    TypedValue.COMPLEX_UNIT_SP, 16, dm));
            // 设置Tab Indicator的颜色
            tabs.setIndicatorColor(Color.parseColor("#45c01a"));
            // 设置选中Tab文字的颜色 (这是我自定义的一个方法)
            tabs.setSelectedTextColor(Color.parseColor("#45c01a"));
            // 取消点击Tab时的背景色
            tabs.setTabBackground(0);
        }
     
        public class MyPagerAdapter extends FragmentPagerAdapter {
     
            public MyPagerAdapter(FragmentManager fm) {
                super(fm);
            }
     
            private final String[] titles = { "聊天""发现""通讯录" };
     
            @Override
            public CharSequence getPageTitle(int position) {
                return titles[position];
            }
     
            @Override
            public int getCount() {
                return titles.length;
            }
     
            @Override
            public Fragment getItem(int position) {
                switch (position) {
                case 0:
                    if (chatFragment == null) {
                        chatFragment = new ChatFragment();
                    }
                    return chatFragment;
                case 1:
                    if (foundFragment == null) {
                        foundFragment = new FoundFragment();
                    }
                    return foundFragment;
                case 2:
                    if (contactsFragment == null) {
                        contactsFragment = new ContactsFragment();
                    }
                    return contactsFragment;
                default:
                    return null;
                }
            }
     
        }
     
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
     
        @Override
        public boolean onMenuOpened(int featureId, Menu menu) {
            if (featureId == Window.FEATURE_ACTION_BAR && menu != null) {
                if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
                    try {
                        Method m = menu.getClass().getDeclaredMethod(
                                "setOptionalIconsVisible", Boolean.TYPE);
                        m.setAccessible(true);
                        m.invoke(menu, true);
                    } catch (Exception e) {
                    }
                }
            }
            return super.onMenuOpened(featureId, menu);
        }
     
        private void setOverflowShowingAlways() {
            try {
                ViewConfiguration config = ViewConfiguration.get(this);
                Field menuKeyField = ViewConfiguration.class
                        .getDeclaredField("sHasPermanentMenuKey");
                menuKeyField.setAccessible(true);
                menuKeyField.setBoolean(config, false);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
     
    } 
     
     
     
     
     
     





    qq3061280@163.com
  • 相关阅读:
    Android的NDK开发(5)————Android JNI层实现文件的read、write与seek操作
    android Context
    android 控件放在 listview 的下方 并且在 屏幕底部
    android Activity 布局 和 控件属性
    有关vtun和虚拟网卡要做的实验
    android xml pull 解析 豆瓣书籍
    android UI设计之 背景透明色 项目资源文件关系
    android 资源引用 自定义标题栏
    真机调试Unable to open sync connection!
    C++ 编译预处理
  • 原文地址:https://www.cnblogs.com/aibuli/p/193c47215cfe799c413efbd5aab29afa.html
Copyright © 2020-2023  润新知