Android仿微信公众号界面

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

微信公众平台现在分为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;

@Override

protected 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);

}

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

int 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() {

@Override

public void onFocusChange(View v, boolean hasFocus) {

// TODO Auto-generated method stub

if (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,用户为1

map.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;

}

@Override

public int getCount() {

// TODO Auto-generated method stub

return list.size();

}

@Override

public Object getItem(int position) {

// TODO Auto-generated method stub

return list.get(position);

}

@Override

public long getItemId(int position) {

// TODO Auto-generated method stub

return position;

}

@Override

public View getView(int position, View convertView, ViewGroup parent) {

// TODO Auto-generated method stub

ViewHolder 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个。

以上是 Android仿微信公众号界面 的全部内容, 来源链接: utcz.com/p/240670.html

回到顶部