仿微信公众号界面实现

来源:互联网 发布:opencv读取caffe 编辑:程序博客网 时间:2024/05/16 18:33

最近在做一个关于微信公众平台服务号的小项目,主要用来实现排队叫号功能。一直都对微信公众号开发比较好奇,于是趁这次机会仔细研究了一下公众号的开发流程和逻辑架构。

微信公众平台现在分为3类:订阅号,服务号和企业号。其中,服务号和企业号的开放权限比较高,可以实现自定义菜单功能,调用摄像头以及LBS等API。

基本通信架构如图:


在项目的功能设计阶段本想搭建一个服务号Demo用来展示,但微信服务号的认证手续太麻烦,而且我也没有那个资质去开通服务号。于是打算自己做一个仿微信公众号的基本界面,先实现菜单功能,避免开发初期的公众号注册,同时也方便展示。

先上效果图:

  


1. 界面布局

主界面布局四部分,由上到下依次是:标题栏,消息列表,底部菜弹出的子菜单,底部菜单或输入栏。

主界面基本框架main.xml代码如下:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="#E4E4E4" >    <!-- 消息列表 -->    <ListView        android:id="@+id/lv"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:layout_marginBottom="50dp"        android:layout_marginTop="10dp"        android:cacheColorHint="#00000000"        android:divider="#00000000"        android:dividerHeight="20dp"        android:scrollbars="none" >    </ListView>    <!-- 点击底部菜单后弹出的子菜单 -->    <LinearLayout        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_gravity="bottom"        android:layout_marginBottom="50dp"        android:orientation="horizontal" >        <View            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="0.5" />        <LinearLayout            android:id="@+id/pop_layout1"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_gravity="bottom"            android:layout_weight="1"            android:orientation="vertical" >        </LinearLayout>        <LinearLayout            android:id="@+id/pop_layout2"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_gravity="bottom"            android:layout_weight="1"            android:orientation="vertical" >        </LinearLayout>        <LinearLayout            android:id="@+id/pop_layout3"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_gravity="bottom"            android:layout_weight="1"            android:orientation="vertical" >        </LinearLayout>    </LinearLayout>        <!-- 底部菜单 -->    <LinearLayout        android:id="@+id/bottom_layout"        android:layout_width="fill_parent"        android:layout_height="50dp"        android:layout_gravity="bottom"        android:background="#00ffffff"        android:orientation="vertical" >        <LinearLayout            android:id="@+id/bottom_menu_layout1"            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:background="#ffffff"            android:orientation="vertical" >            <View                android:layout_width="fill_parent"                android:layout_height="1px"                android:background="#A6A6A6" />            <LinearLayout                android:id="@+id/menu_layout"                android:layout_width="fill_parent"                android:layout_height="fill_parent"                android:gravity="center"                android:orientation="horizontal" >                <ImageView                    android:id="@+id/keyboard"                    android:layout_width="0dp"                    android:layout_height="wrap_content"                    android:layout_marginBottom="5dp"                    android:layout_marginLeft="3dp"                    android:layout_marginRight="3dp"                    android:layout_marginTop="5dp"                    android:layout_weight="0.5"                    android:background="@drawable/keyboard" />                <View                    android:layout_width="1px"                    android:layout_height="fill_parent"                    android:background="#A6A6A6" />                <RelativeLayout                    android:id="@+id/btn1"                    android:layout_width="0dp"                    android:layout_height="fill_parent"                    android:layout_weight="1"                    android:background="@drawable/btn_selector" >                    <RelativeLayout                        android:layout_width="fill_parent"                        android:layout_height="fill_parent"                        android:layout_margin="5dp" >                        <TextView                            android:id="@+id/text1"                            android:layout_width="fill_parent"                            android:layout_height="fill_parent"                            android:layout_centerInParent="true"                            android:gravity="center"                            android:text="用户绑定"                            android:textColor="#000000"                            android:textSize="16sp" />                        <ImageView                            android:layout_width="10dp"                            android:layout_height="10dp"                            android:layout_alignParentBottom="true"                            android:layout_alignParentRight="true"                            android:src="@drawable/more_icon"                            android:visibility="invisible" />                    </RelativeLayout>                </RelativeLayout>                <View                    android:layout_width="1px"                    android:layout_height="fill_parent"                    android:background="#A6A6A6" />                <RelativeLayout                    android:id="@+id/btn2"                    android:layout_width="0dp"                    android:layout_height="fill_parent"                    android:layout_weight="1"                    android:background="@drawable/btn_selector" >                    <RelativeLayout                        android:layout_width="fill_parent"                        android:layout_height="fill_parent"                        android:layout_margin="5dp" >                        <TextView                            android:id="@+id/text2"                            android:layout_width="fill_parent"                            android:layout_height="fill_parent"                            android:layout_centerInParent="true"                            android:gravity="center"                            android:text="扫描签到"                            android:textColor="#000000"                            android:textSize="16sp" />                        <ImageView                            android:layout_width="10dp"                            android:layout_height="10dp"                            android:layout_alignParentBottom="true"                            android:layout_alignParentRight="true"                            android:src="@drawable/more_icon"                            android:visibility="invisible" />                    </RelativeLayout>                </RelativeLayout>                <View                    android:layout_width="1px"                    android:layout_height="fill_parent"                    android:background="#A6A6A6" />                <RelativeLayout                    android:id="@+id/btn3"                    android:layout_width="0dp"                    android:layout_height="fill_parent"                    android:layout_weight="1"                    android:background="@drawable/btn_selector" >                    <RelativeLayout                        android:layout_width="fill_parent"                        android:layout_height="fill_parent"                        android:layout_margin="5dp" >                        <TextView                            android:id="@+id/text3"                            android:layout_width="fill_parent"                            android:layout_height="fill_parent"                            android:layout_centerInParent="true"                            android:gravity="center"                            android:text="更多"                            android:textColor="#000000"                            android:textSize="16sp" />                        <ImageView                            android:layout_width="10dp"                            android:layout_height="10dp"                            android:layout_alignParentBottom="true"                            android:layout_alignParentRight="true"                            android:src="@drawable/more_icon"                            android:visibility="visible" />                    </RelativeLayout>                </RelativeLayout>            </LinearLayout>        </LinearLayout>    </LinearLayout></FrameLayout>

标题栏title_bar.xml布局如下:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="horizontal" >    <!-- 返回 -->    <ImageView        android:id="@+id/title_bar_back_btn"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentLeft="true"        android:layout_centerVertical="true"        android:layout_marginLeft="10dip"        android:src="@drawable/back" />        <!-- 服务号名称 -->    <TextView        android:id="@+id/my_setting_title_tv"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:text="腾讯招聘面试服务"        android:textColor="#ffffff"        android:textSize="20sp" />        <!-- 服务号 -->    <ImageView        android:id="@+id/title_bar_my"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentRight="true"        android:layout_centerVertical="true"        android:layout_marginRight="10dip"        android:src="@drawable/my" /></RelativeLayout>

完成title_bar布局后,再在values\styles.xml添加自定义标题栏主题

<!-- 自定义标题栏背景颜色 -->    <style name="CustomWindowTitleBackground">        <item name="android:background">#32394A</item>    </style>    <!-- 自定义标题栏主题 -->    <style name="myTheme" parent="android:Theme">        <item name="android:windowTitleSize">45dp</item>        <item name="android:windowTitleBackgroundStyle">@style/CustomWindowTitleBackground</item>    </style>
消息列表的服务端消息item布局item_left.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="horizontal" >    <RelativeLayout        android:layout_width="0dp"        android:layout_height="fill_parent"        android:layout_weight="4" >        <ImageView            android:id="@+id/server_image"             android:layout_width="40dp"            android:layout_height="40dp"            android:layout_marginLeft="2dp"            android:background="@drawable/qq"/>        <TextView             android:id="@+id/server_text"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginLeft="2dp"            android:layout_toRightOf="@id/server_image"            android:background="@drawable/text_bg_left1"            android:gravity="center_vertical|left"            android:textSize="16sp"            android:textColor="#000000"/>    </RelativeLayout>    <View        android:layout_width="0dp"        android:layout_height="fill_parent"        android:layout_weight="1" /></LinearLayout>
消息列表的用户消息item布局item_right.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="horizontal" >    <View        android:layout_width="0dp"        android:layout_height="fill_parent"        android:layout_weight="1" />    <RelativeLayout        android:layout_width="0dp"        android:layout_height="fill_parent"        android:layout_weight="4" >        <ImageView            android:id="@+id/user_image"            android:layout_width="40dp"            android:layout_height="40dp"            android:layout_alignParentRight="true"            android:layout_marginRight="2dp"            android:background="@drawable/qq" />        <TextView            android:id="@+id/user_text"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginRight="1dp"            android:layout_toLeftOf="@id/user_image"            android:background="@drawable/text_bg_right1"            android:gravity="center_vertical|right"            android:textColor="#000000"            android:textSize="16sp" />    </RelativeLayout></LinearLayout>
弹出的子菜单布局child_menu.xml如下:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/child_layout"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:background="#FFFFFF"    android:gravity="bottom"    android:orientation="vertical" >    <RelativeLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content" >        <Button            android:id="@+id/test1"            android:layout_width="wrap_content"            android:layout_height="45dp"            android:background="@drawable/btn_selector"            android:paddingLeft="10dp"            android:paddingRight="10dp"            android:text="进度查询"            android:textColor="#000000"            android:textSize="16sp" />        <View            android:layout_width="wrap_content"            android:layout_height="1px"            android:layout_alignLeft="@id/test1"            android:layout_alignRight="@id/test1"            android:layout_below="@id/test1"            android:background="#E4E4E4" />    </RelativeLayout>    <RelativeLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content" >        <Button            android:id="@+id/test1"            android:layout_width="wrap_content"            android:layout_height="45dp"            android:background="@drawable/btn_selector"            android:paddingLeft="10dp"            android:paddingRight="10dp"            android:text="使用帮助"            android:textColor="#000000"            android:textSize="16sp" />        <View            android:layout_width="wrap_content"            android:layout_height="1px"            android:layout_alignLeft="@id/test1"            android:layout_alignRight="@id/test1"            android:layout_below="@id/test1"            android:background="#E4E4E4" />    </RelativeLayout>    <RelativeLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content" >        <Button            android:id="@+id/test1"            android:layout_width="wrap_content"            android:layout_height="45dp"            android:background="@drawable/btn_selector"            android:paddingLeft="10dp"            android:paddingRight="10dp"            android:text="联系我们"            android:textColor="#000000"            android:textSize="16sp" />        <View            android:layout_width="wrap_content"            android:layout_height="1px"            android:layout_alignLeft="@id/test1"            android:layout_alignRight="@id/test1"            android:layout_below="@id/test1"            android:background="#E4E4E4" />    </RelativeLayout></LinearLayout>

由底部菜单切换到输入框,输入框bottom_menu_layout2.xml布局如下:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <LinearLayout        android:id="@+id/bottom_menu_layout2"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:background="#ffffff"        android:orientation="vertical" >        <View            android:layout_width="fill_parent"            android:layout_height="1px"            android:background="#A6A6A6" />        <LinearLayout            android:id="@+id/menu_layout"            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:gravity="center"            android:orientation="horizontal" >            <!-- 左侧切换菜单按钮 -->            <ImageView                android:id="@+id/menu"                android:layout_width="0dp"                android:layout_height="wrap_content"                android:layout_marginBottom="5dp"                android:layout_marginLeft="3dp"                android:layout_marginRight="3dp"                android:layout_marginTop="5dp"                android:layout_weight="0.5"                android:background="@drawable/menu" />            <View                android:layout_width="1px"                android:layout_height="fill_parent"                android:background="#A6A6A6" />            <RelativeLayout                android:id="@+id/btn1"                android:layout_width="0dp"                android:layout_height="fill_parent"                android:layout_margin="5dp"                android:layout_weight="3"                android:background="#ffffff" >                <ImageView                    android:id="@+id/voice"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_alignParentLeft="true"                    android:layout_centerInParent="true"                    android:layout_marginLeft="5dp"                    android:src="@drawable/voice" />                <!-- 右侧“+”按钮或发送按钮 -->                <Button                    android:id="@+id/add"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_alignParentRight="true"                    android:layout_centerInParent="true"                    android:layout_marginRight="1dp"                    android:background="@drawable/add"                    android:paddingBottom="5dp"                    android:paddingLeft="8dp"                    android:paddingRight="8dp"                    android:paddingTop="5dp"                    android:text=""                    android:textColor="#ffffff"                    android:textSize="14sp" />                <!-- 输入 -->                <RelativeLayout                    android:layout_width="fill_parent"                    android:layout_height="wrap_content"                    android:layout_centerInParent="true"                    android:layout_marginLeft="5dp"                    android:layout_marginRight="5dp"                    android:layout_toLeftOf="@id/add"                    android:layout_toRightOf="@id/voice" >                    <EditText                        android:id="@+id/input_text"                        android:layout_width="fill_parent"                        android:layout_height="wrap_content"                        android:layout_centerVertical="true"                        android:background="#00000000"                        android:gravity="bottom"                        android:paddingLeft="2dp"                        android:paddingRight="2dp"                        android:text=""                        android:textColor="#000000"                        android:textSize="16sp" />                    <View                        android:layout_width="fill_parent"                        android:layout_height="1px"                        android:layout_below="@id/input_text"                        android:layout_marginTop="10dp"                        android:background="#A6A6A6" />                </RelativeLayout>            </RelativeLayout>        </LinearLayout>    </LinearLayout></LinearLayout>

2. 代码实现

MainActivity.java

package com.example.wxdemo;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import android.os.Bundle;import android.app.Activity;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnFocusChangeListener;import android.view.ViewGroup;import android.view.Window;import android.view.animation.Animation;import android.view.animation.AnimationUtils;import android.widget.BaseAdapter;import android.widget.Button;import android.widget.EditText;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.ListView;import android.widget.RelativeLayout;import android.widget.TextView;public class MainActivity extends Activity implements View.OnClickListener {private LinearLayout bottomLayout;// 底部菜单父框架private LinearLayout bottomMenuLayout1;// 底部菜单布局private LinearLayout bottomMenuLayout2;// 底部输入框布局private RelativeLayout btn1;// “用户绑定”按钮布局private RelativeLayout btn2;// “扫描签到”按钮布局private RelativeLayout btn3;// “更多”按钮布局private LinearLayout popLayout1;private LinearLayout popLayout2;private LinearLayout popLayout3;// 弹出的子菜单父框架布局private LinearLayout childLayout;// “更多”按钮的子菜单private ListView lv;private MyAdapter adapter;private List<Map<String, String>> listData = new ArrayList<Map<String, String>>();private ImageView keyboard;// 底部键盘切换图标private ImageView menu;// 底部菜单切换图标private Button send;// 发送按钮private EditText inputText;// 输入框private boolean open = true;// 子菜单填充状态标记private boolean flag = false;// 子菜单显示状态标记private boolean bind = false;// 用户绑定状态标记private Animation animEnter;// 底部菜单进入动画private Animation animExit;// 底部菜单退出动画private View view;private View view2;private LayoutInflater inflater;private int myID = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);this.requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);setContentView(R.layout.main);getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.title_bar);// 自定义标题栏inflater = MainActivity.this.getLayoutInflater();popLayout1 = (LinearLayout) findViewById(R.id.pop_layout1);popLayout2 = (LinearLayout) findViewById(R.id.pop_layout2);popLayout3 = (LinearLayout) findViewById(R.id.pop_layout3);bottomLayout = (LinearLayout) findViewById(R.id.bottom_layout);bottomMenuLayout1 = (LinearLayout) findViewById(R.id.bottom_menu_layout1);keyboard = (ImageView) findViewById(R.id.keyboard);btn1 = (RelativeLayout) findViewById(R.id.btn1);btn2 = (RelativeLayout) findViewById(R.id.btn2);btn3 = (RelativeLayout) findViewById(R.id.btn3);lv = (ListView) findViewById(R.id.lv);btn1.setOnClickListener(this);btn2.setOnClickListener(this);btn3.setOnClickListener(this);keyboard.setOnClickListener(this);adapter = new MyAdapter(this, listData);lv.setAdapter(adapter);}@Overridepublic void onClick(View v) {// TODO Auto-generated method stubint id = v.getId();switch (id) {case R.id.btn1:btn1Click();break;case R.id.btn2:break;case R.id.btn3:btn3Click();break;case R.id.keyboard:keyboardClick();break;case R.id.menu:menuClick();break;case R.id.add:sendClick();break;default:break;}}public void btn1Click() {// 用户绑定Map<String, String> map = new HashMap<String, String>();map.put("type", "0");if (!bind) {map.put("text", "请输入您的手机号或简历ID进行帐号绑定,绑定成功后才能进行签到。");} else {map.put("text", "帐号已绑定成功,请您准时签到。");}listData.add(map);adapter.notifyDataSetChanged();}public void btn2Click() {// 扫描签到// TODO}public void btn3Click() {// 更多if (open == true) {view = inflater.inflate(R.layout.child_menu, popLayout3, true);childLayout = (LinearLayout) view.findViewById(R.id.child_layout);open = false;}if (flag == false) {flag = true;childLayout.setVisibility(View.VISIBLE);} else {flag = false;childLayout.setVisibility(View.GONE);}}public void keyboardClick() {//点击键盘按钮,由底部菜单切换为底部输入view2 = inflater.inflate(R.layout.bottom_menu_layout2, bottomLayout,true);bottomMenuLayout2 = (LinearLayout) view2.findViewById(R.id.bottom_menu_layout2);animEnter = AnimationUtils.loadAnimation(MainActivity.this,R.anim.my_pop_enter_anim);animExit = AnimationUtils.loadAnimation(MainActivity.this,R.anim.my_pop_exit_anim);animEnter.setStartOffset(200);bottomMenuLayout1.startAnimation(animExit);bottomMenuLayout1.setVisibility(View.GONE);bottomMenuLayout2.startAnimation(animEnter);bottomMenuLayout2.setVisibility(View.VISIBLE);menu = (ImageView) view2.findViewById(R.id.menu);inputText = (EditText) view2.findViewById(R.id.input_text);send = (Button) view2.findViewById(R.id.add);menu.setOnClickListener(this);send.setOnClickListener(this);inputClick();}public void menuClick() {//点击菜单按钮,由底部输入框切换为底部菜单bottomMenuLayout2.startAnimation(animExit);bottomMenuLayout2.setVisibility(View.GONE);bottomMenuLayout1.startAnimation(animEnter);bottomMenuLayout1.setVisibility(View.VISIBLE);}public void inputClick() {inputText.setOnFocusChangeListener(new OnFocusChangeListener() {@Overridepublic void onFocusChange(View v, boolean hasFocus) {// TODO Auto-generated method stubif (hasFocus) {send.setBackgroundResource(R.drawable.send_btn_bg);send.setText("发送");} else {send.setBackgroundResource(R.drawable.add);send.setText("  ");}}});}public void sendClick() {String text = inputText.getEditableText().toString();inputText.setText("");if (text != null && (!text.equals(""))) {Map<String, String> map;map = new HashMap<String, String>();map.put("type", "1");// 消息类型,服务端为0,用户为1map.put("text", text);listData.add(map);map = new HashMap<String, String>();map.put("type", "0");map.put("text", "帐号已绑定成功,请您准时签到。");listData.add(map);adapter.notifyDataSetChanged();bind = true;}}private class MyAdapter extends BaseAdapter {public List<Map<String, String>> list;private Context context;private int type;private ListView listView;public MyAdapter(Context context, List<Map<String, String>> list) {this.context = context;this.list = list;}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn list.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn list.get(position);}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubViewHolder viewHolder = null;Map<String, String> map = (Map<String, String>) list.get(position);if (map.get("type").equals("0")) {// 服务端if (convertView == null) {convertView = inflater.inflate(R.layout.item_left, parent,false);viewHolder = new ViewHolder();viewHolder.mTextView = (TextView) convertView.findViewById(R.id.server_text);viewHolder.mImageView = (ImageView) convertView.findViewById(R.id.server_image);convertView.setTag(viewHolder);} else {viewHolder = (ViewHolder) convertView.getTag();}viewHolder.mTextView.setText(map.get("text"));} else {// 用户if (convertView == null) {convertView = inflater.inflate(R.layout.item_right, parent,false);viewHolder = new ViewHolder();viewHolder.mTextView = (TextView) convertView.findViewById(R.id.user_text);viewHolder.mImageView = (ImageView) convertView.findViewById(R.id.user_image);convertView.setTag(viewHolder);} else {viewHolder = (ViewHolder) convertView.getTag();}viewHolder.mTextView.setText(map.get("text"));}return convertView;}}private final class ViewHolder {TextView mTextView;ImageView mImageView;}}

以上就是实现仿微信服务号的主要代码,菜单功能并没用完全实现,可根据实际情况和需要进行添加。同时还需注意的是,底部菜单最多为3个,每个名称限制在7个字符,包含的子菜单最多只能有5个。




0 0