最近由于公司项目的界面需求,软件的主界面与微信的基本上差不多,于是花一点时间研究并实现了一下,用到了一些第三方的开源项目和android-support-v7兼容包,
主要用到了如下开源项目:
- PagerSlidingTabStrip (标签页的滑动)
- android-viewbadger (未读信息的提醒标识)
要说明的是PagerSlidingTabStrip我为了一些效果的需要自己作了一些改进和扩展,不然是无法达到所需的效果的,直接上效果图吧。
这里讲解一下标签的滑动,PagerSlidingTabStrip得到viewpager里的fragment的数量,获得屏幕的宽度,然后根据标签的数量来计算每个indicator的平均长度,当页面滑动时,根据当前页面的索引位置来获得对应的子控件,并条用scrollTo方法来滑动对应的位置,indicator的结构如图所示。
Textview用来显示标题的文字,后后面的view主要是用来显示未读信息的数量,因为BadgeView需要一个载体来显示信息。
MainActiivty.java的主要代码:
package com.example.mymicromsgdemo;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.Gravity;
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.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;
import com.example.mymicromsgdemo.util.SystemUtil;
import com.example.mymicromsgdemo.view.BadgeView;
import com.example.mymicromsgdemo.view.PagerSlidingTabStrip;
public class MainActivity extends ActionBarActivity {
private Context mContext;
private static String[] contentLables;
private static int[] homeMenuPlusRes = {
R.drawable.ic_launcher,
R.drawable.ic_launcher,
R.drawable.ic_launcher,
R.drawable.ic_launcher,
R.drawable.ic_launcher
};
private static int[] menu_popup_more_res = { R.drawable.ic_launcher, R.drawable.ic_launcher };
private static String[] menu_popup_plus_title = { "发起群聊", "添加朋友", "视频聊天", "扫一扫", "拍照" };
private static String[] menu_popup_more_title = { "张三", "设置" };
public static int CONTENT_HEIGHT = 0;
private PopupWindow mPopupWindowAdd;
private PopupWindow mPopupWindowMore;
private View popupAddParent;
private View popupMoreParent;
private PagerSlidingTabStrip indicator;
MyFragmentPagerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
ActionBar actionBar = getSupportActionBar();
actionBar.setTitle("微信");
contentLables = getResources().getStringArray(R.array.home_function_lable);
adapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
indicator = (PagerSlidingTabStrip) findViewById(R.id.indicator);
indicator.setViewPager(pager);
new LoadDataTAsk().execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu_home, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_search: //搜索
//openSearch();
break;
case R.id.action_add: //添加
if (popupAddParent == null) {
popupAddParent = findViewById(R.id.action_add);
}
showAddPopupWindow(popupAddParent);
break;
case R.id.action_more: //更多
if (popupMoreParent == null) {
popupMoreParent = findViewById(R.id.action_more);
}
showMorePopupWindow(popupMoreParent);
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
/**
* 初始化右上角菜单的资源
* @param resIds 图标资源数组
* @param titles 菜单标题数组
* @return 菜单列表
*/
private List<MenuPopupItem> initMenus(int[] resIds, String[] titles) {
List<MenuPopupItem> list = new ArrayList<MenuPopupItem>();
int len = titles.length;
for (int i = 0; i < len; i++) {
MenuPopupItem item = new MenuPopupItem(mContext.getResources().getDrawable(resIds[i]), titles[i]);
list.add(item);
}
return list;
}
/**
* 创建并显示“添加”的popup菜单
* @param parent
*/
private void showAddPopupWindow(final View parent) {
if (mPopupWindowAdd == null) {
View view = LayoutInflater.from(mContext).inflate(R.layout.menu_home, null);
ListView listView = (ListView) view.findViewById(R.id.lv_menu_popup);
MemuPopupAdapter menuAddAdapter = new MemuPopupAdapter(mContext, initMenus(homeMenuPlusRes, menu_popup_plus_title));
listView.setAdapter(menuAddAdapter);
mPopupWindowAdd = new PopupWindow(view, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
initPopupWindow(mPopupWindowAdd);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
togglePopupWindow(mPopupWindowAdd, parent);
}
});
}
togglePopupWindow(mPopupWindowAdd, parent);
}
/**
* 创建并显示“更多”的popup菜单
* @param parent
*/
private void showMorePopupWindow(final View parent) {
if (mPopupWindowMore == null) {
View view = LayoutInflater.from(mContext).inflate(R.layout.menu_home, null);
ListView listView = (ListView) view.findViewById(R.id.lv_menu_popup);
MemuPopupAdapter menuAddAdapter = new MemuPopupAdapter(mContext, initMenus(menu_popup_more_res, menu_popup_more_title));
listView.setAdapter(menuAddAdapter);
mPopupWindowMore = new PopupWindow(view, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
initPopupWindow(mPopupWindowMore);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
togglePopupWindow(mPopupWindowMore, parent);
}
});
}
togglePopupWindow(mPopupWindowMore, parent);
}
/**
* 初始化popupWindow的一些参数,主要用于菜单的显示方式
* @param window
*/
private void initPopupWindow(PopupWindow window) {
View view = window.getContentView();
window.setWidth(SystemUtil.getViewSize(view)[0] + 35);
window.setOutsideTouchable(true);
window.setFocusable(true);
window.update();
window.setBackgroundDrawable(new BitmapDrawable(null, (Bitmap) null));
window.setAnimationStyle(R.style.MenuPopupAnimStyle);
}
/**
* 显示与消失popup菜单
* @param window
* @param parent
*/
private void togglePopupWindow(PopupWindow window, View parent) {
if (window.isShowing()) {
window.dismiss();
} else {
if (parent != null) {
window.showAtLocation(parent, Gravity.TOP | Gravity.RIGHT, 5, SystemUtil.getStatusBarHeight(mContext) + SystemUtil.getActionBarHeight(mContext));
}
}
}
/**
* 异步加载数据的线程
*/
class LoadDataTAsk extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
//1、在这里可以加载数据
return null;
}
@Override
protected void onPostExecute(Void result) {
//1、加载数据完毕后,更新界面
//2、显示未读信息的提醒数量
int count = contentLables.length;
for(int i = 0; i < count; i++) {
View view = indicator.getCurrentTargetView(i);
if(i == 0) { //显示具体数量的提醒
showBadgeView(mContext, view, 23);
} else {
showBadgeView(mContext, view, 0);
}
}
}
}
private void showBadgeView(Context context, View target, int num) {
BadgeView badgeView = new BadgeView(mContext, target);
badgeView.setTextSize(10);
badgeView.setGravity(Gravity.CENTER);
badgeView.setBadgePosition(BadgeView.POSITION_VERTICAL_LEFT);
if(num == 0) {
badgeView.setText("");
badgeView.setBackgroundResource(R.drawable.main_tab_new_message_notify);
} else {
badgeView.setText(String.valueOf(num));
badgeView.setBackgroundResource(R.drawable.g_unread_messages_bg);
}
badgeView.show();
}
/**
* popup菜单的适配器
*/
class MemuPopupAdapter extends BaseAdapter {
private Context context;
private List<MenuPopupItem> list;
public MemuPopupAdapter(Context context, List<MenuPopupItem> list) {
super();
this.context = context;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
MenuViewHolder holder = null;
if (convertView == null) {
holder = new MenuViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.item_menu_popu, parent, false);
ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_menu_icon);
TextView textView = (TextView) convertView.findViewById(R.id.tv_menu_title);
holder.icon = imageView;
holder.title = textView;
convertView.setTag(holder);
} else {
holder = (MenuViewHolder) convertView.getTag();
}
MenuPopupItem item = list.get(position);
Drawable icon = item.getIcon();
String title = item.getTitle();
if (icon == null) {
holder.icon.setVisibility(View.GONE);
} else {
holder.icon.setImageDrawable(icon);
}
holder.title.setText(title);
return convertView;
}
final class MenuViewHolder {
ImageView icon;
TextView title;
}
}
class MyFragmentPagerAdapter extends FragmentPagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return TestFragment.newInstance("测试内容" + (position + 1));
}
@Override
public CharSequence getPageTitle(int position) {
return contentLables[position % contentLables.length].toUpperCase(Locale.getDefault());
}
@Override
public int getCount() {
return contentLables.length;
}
}
}
布局文件activity_main.xml的主要代码为:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:psts="http://schemas.android.com/apk/res/com.example.mymicromsgdemo"
android:orientation="vertical"
android:layout_width="fill_parent"
android:background="#ffffff"
android:layout_height="fill_parent">
<com.example.mymicromsgdemo.view.PagerSlidingTabStrip
android:id="@+id/indicator"
android:layout_height="40dp"
android:layout_width="fill_parent"
psts:pstsDividerColor="@android:color/transparent"
psts:pstsUnderlineHeight="1dp"
psts:pstsIndicatorHeight="4dp"
psts:pstsIndicatorColor="@color/pager_tab_indicator_color"
psts:pstsSelectedTabTextColor="@color/pager_tab_indicator_color"
psts:pstsTabBackground="@android:color/transparent"
android:textSize="16sp"/>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
</LinearLayout>
为了兼容Android2.X,本项目采用android-support-v7的兼容包来实现actionbar,当然,也有一些第三方的优秀的包可以做到,如大名鼎鼎的 ActionBarSherlock。要在actionbar上弹出微信那样效果的效果,在4.X是很容易实现的,但为了兼容2.x,这里用普通的munu可能不好实现,自己暂时木有想到,有想到的朋友可以探讨一下,于是就使用了popupwindow来实现,主要的原理是在actionbar的菜单项中相应点击事件,然后来弹出菜单。
系统的菜单menu_home.xml源码如下。
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/action_search"
android:orderInCategory="100"
app:showAsAction="always"
android:title="搜索"
android:icon="@drawable/system_menu_search_normal" />
<item
android:id="@+id/action_add"
android:orderInCategory="101"
app:showAsAction="always"
android:title="添加"
android:icon="@drawable/system_menu_plus_normal"/>
<item
android:id="@+id/action_more"
android:orderInCategory="102"
app:showAsAction="always"
android:title="更多"
android:icon="@drawable/system_menu_more_normal" />
</menu>
注意:这里 xmlns:app="http://schemas.android.com/apk/res-auto"意思是使用support-v7的资源,不然在2.x是显示不出来的。
popupwindow的显示条用了window.showAtLocation方法,具体的位置是x轴距右5个像素,y轴是通过计算出来的,y=屏幕的高度-状态栏的高度-actionbar的高度,当然,也可以用showAsDropDown方法来显,大家可以自己试一下。
好了,大致的内容就是这些,大家有什么疑问或者文中有什么问题可以指正。
Email:huanghui6579@163.com
QQ:409384897