失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 仿微信公众号界面实现

仿微信公众号界面实现

时间:2023-09-20 05:55:07

相关推荐

仿微信公众号界面实现

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

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

基本通信架构如图:

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

先上效果图:

1. 界面布局

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

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

<FrameLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#E4E4E4" ><!-- 消息列表 --><ListViewandroid: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><!-- 点击底部菜单后弹出的子菜单 --><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_gravity="bottom"android:layout_marginBottom="50dp"android:orientation="horizontal" ><Viewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="0.5" /><LinearLayoutandroid: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><LinearLayoutandroid: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><LinearLayoutandroid: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><!-- 底部菜单 --><LinearLayoutandroid:id="@+id/bottom_layout"android:layout_width="fill_parent"android:layout_height="50dp"android:layout_gravity="bottom"android:background="#00ffffff"android:orientation="vertical" ><LinearLayoutandroid:id="@+id/bottom_menu_layout1"android:layout_width="fill_parent"android:layout_height="fill_parent"android:background="#ffffff"android:orientation="vertical" ><Viewandroid:layout_width="fill_parent"android:layout_height="1px"android:background="#A6A6A6" /><LinearLayoutandroid:id="@+id/menu_layout"android:layout_width="fill_parent"android:layout_height="fill_parent"android:gravity="center"android:orientation="horizontal" ><ImageViewandroid: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" /><Viewandroid:layout_width="1px"android:layout_height="fill_parent"android:background="#A6A6A6" /><RelativeLayoutandroid:id="@+id/btn1"android:layout_width="0dp"android:layout_height="fill_parent"android:layout_weight="1"android:background="@drawable/btn_selector" ><RelativeLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_margin="5dp" ><TextViewandroid: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" /><ImageViewandroid: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><Viewandroid:layout_width="1px"android:layout_height="fill_parent"android:background="#A6A6A6" /><RelativeLayoutandroid:id="@+id/btn2"android:layout_width="0dp"android:layout_height="fill_parent"android:layout_weight="1"android:background="@drawable/btn_selector" ><RelativeLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_margin="5dp" ><TextViewandroid: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" /><ImageViewandroid: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><Viewandroid:layout_width="1px"android:layout_height="fill_parent"android:background="#A6A6A6" /><RelativeLayoutandroid:id="@+id/btn3"android:layout_width="0dp"android:layout_height="fill_parent"android:layout_weight="1"android:background="@drawable/btn_selector" ><RelativeLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_margin="5dp" ><TextViewandroid: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" /><ImageViewandroid: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="/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="horizontal" ><!-- 返回 --><ImageViewandroid: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" /><!-- 服务号名称 --><TextViewandroid: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" /><!-- 服务号 --><ImageViewandroid: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="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal" ><RelativeLayoutandroid:layout_width="0dp"android:layout_height="fill_parent"android:layout_weight="4" ><ImageViewandroid: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><Viewandroid: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="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal" ><Viewandroid:layout_width="0dp"android:layout_height="fill_parent"android:layout_weight="1" /><RelativeLayoutandroid:layout_width="0dp"android:layout_height="fill_parent"android:layout_weight="4" ><ImageViewandroid:id="@+id/user_image"android:layout_width="40dp"android:layout_height="40dp"android:layout_alignParentRight="true"android:layout_marginRight="2dp"android:background="@drawable/qq" /><TextViewandroid: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="/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" ><RelativeLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content" ><Buttonandroid: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" /><Viewandroid: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><RelativeLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content" ><Buttonandroid: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" /><Viewandroid: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><RelativeLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content" ><Buttonandroid: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" /><Viewandroid: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="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><LinearLayoutandroid:id="@+id/bottom_menu_layout2"android:layout_width="fill_parent"android:layout_height="fill_parent"android:background="#ffffff"android:orientation="vertical" ><Viewandroid:layout_width="fill_parent"android:layout_height="1px"android:background="#A6A6A6" /><LinearLayoutandroid:id="@+id/menu_layout"android:layout_width="fill_parent"android:layout_height="fill_parent"android:gravity="center"android:orientation="horizontal" ><!-- 左侧切换菜单按钮 --><ImageViewandroid: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" /><Viewandroid:layout_width="1px"android:layout_height="fill_parent"android:background="#A6A6A6" /><RelativeLayoutandroid:id="@+id/btn1"android:layout_width="0dp"android:layout_height="fill_parent"android:layout_margin="5dp"android:layout_weight="3"android:background="#ffffff" ><ImageViewandroid: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" /><!-- 右侧“+”按钮或发送按钮 --><Buttonandroid: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" /><!-- 输入 --><RelativeLayoutandroid: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" ><EditTextandroid: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" /><Viewandroid: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个。

如果觉得《仿微信公众号界面实现》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。