Android仿新版微信主界面(使用android-support-v7兼容包,兼容2.2及其以上版本)

最近由于公司项目的界面需求,软件的主界面与微信的基本上差不多,于是花一点时间研究并实现了一下,用到了一些第三方的开源项目和android-support-v7兼容包,

主要用到了如下开源项目:

  1. PagerSlidingTabStrip (标签页的滑动)
  2. 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



源码下载,点击这里

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值