Android仿微信公眾號界面
最近在做一個關于微信公眾平臺服務號的小項目,主要用來實現(xiàn)排隊叫號功能。一直都對微信公眾號開發(fā)比較好奇,于是趁這次機會仔細研究了一下公眾號的開發(fā)流程和邏輯架構。
微信公眾平臺現(xiàn)在分為3類:訂閱號,服務號和企業(yè)號。其中,服務號和企業(yè)號的開放權限比較高,可以實現(xiàn)自定義菜單功能,調用攝像頭以及LBS等API。
基本通信架構如圖:
在項目的功能設計階段本想搭建一個服務號Demo用來展示,但微信服務號的認證手續(xù)太麻煩,而且我也沒有那個資質去開通服務號。于是打算自己做一個仿微信公眾號的基本界面,先實現(xiàn)菜單功能,避免開發(fā)初期的公眾號注冊,同時也方便展示。
先上效果圖:
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="聯(lián)系我們" 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" /> <!-- 右側“+”按鈕或發(fā)送按鈕 --> <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. 代碼實現(xiàn)
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;// 發(fā)送按鈕 private EditText inputText;// 輸入框 private boolean open = true;// 子菜單填充狀態(tài)標記 private boolean flag = false;// 子菜單顯示狀態(tài)標記 private boolean bind = false;// 用戶綁定狀態(tài)標記 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("發(fā)送"); } 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; } }
以上就是實現(xiàn)仿微信服務號的主要代碼,菜單功能并沒用完全實現(xiàn),可根據(jù)實際情況和需要進行添加。同時還需注意的是,底部菜單最多為3個,每個名稱限制在7個字符,包含的子菜單最多只能有5個。
相關文章
Android使用AlertDialog實現(xiàn)對話框
本文主要介紹了Android使用AlertDialog實現(xiàn)對話框的相關知識,具有很好的參考價值。下面跟著小編一起來看下吧2017-03-03Android學習筆記之ContentProvider和Uri詳解
本篇文章主要介紹了Android學習筆記之ContentProvider和Uri詳解,對于學習Android的朋友具有一定的參考價值,有需要可以可以了解一下。2016-11-11Flutter 底部彈窗ModelBottomSheet的使用示例
在實際開發(fā)過程中,經常會用到底部彈窗來進行快捷操作,例如選擇一個選項,選擇下一步操作等等。在 Flutter 中提供了一個 showModelBottomSheet 方法用于彈出底部彈窗,本篇介紹如何使用底部彈窗。2021-06-06Android P實現(xiàn)靜默安裝的方法示例(官方Demo)
這篇文章主要介紹了Android P實現(xiàn)靜默安裝,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-02-02Android4.4下MediaProvider無法向外置SD卡中文件寫數(shù)據(jù)的解決方法
這篇文章主要介紹了Android4.4下MediaProvider無法向外置SD卡中文件寫數(shù)據(jù)的解決方法,實例分析了Android4.4下針對讀寫限制的修改技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10Android Jetpack Compose實現(xiàn)列表吸頂效果
安卓傳統(tǒng)的Recyclerview打造懸浮頭部StickyHeader的吸頂效果,十分麻煩,而在Compose中就簡單多了。因此,本文將采用Jetpack Compose實現(xiàn)列表吸頂效果,需要的可以參考一下2022-02-02詳解Android?Flutter中SliverAppBar的使用教程
對于一個APP來說,肯定會有一個AppBar,這個AppBar一般包含了APP的導航信息等。在lutter已經為我們提供了一個非常強大的AppBar組件,這個組件叫做SliverAppBar。本文就來聊聊它的具體使用吧2023-01-01