1. 程式人生 > >Android仿微信底部選單欄+今日頭條頂部導航欄

Android仿微信底部選單欄+今日頭條頂部導航欄

背景

Android應用幾乎都會用到底部選單欄,在Material Design還沒有出來之前,TabHost等技術一直佔主流,現在Google新sdk中提供了TabLayout類可以便捷的做出底部選單欄效果。

本節我們實現兩種主要的Tab效果:

  1. 仿微信底部選單
  2. 仿今日頭條頂部導航條

效果預覽:
demo

底部選單

Tab一般與Activity或Fragment配合使用,以達到多頁面切換效果,這裡使用Fragment來開發子介面。

微信形式的底部選單可以理解為一個外層Activity,套用幾個Fragment。頁面佈局層次為:

  • MainActivity 主框架
    • MsgFragment 微信
    • ContactFragment 通訊錄
    • FindFragment 發現
    • MeFragment 我

做出來的效果:
weixin

1、activity_main.xml佈局

ViewPager+TabLayout上下結構:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1" />

    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dip"
        android:background="@color/line_gray" />

    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="54dip"
        app:tabIndicatorHeight="0dip" />

</LinearLayout>

2、MainActivity原始碼

package com.dommy.tab;

import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.dommy.tab.adapter.MainFragmentAdapter;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * 主框架
 */
public class MainActivity extends AppCompatActivity {

    /**
     * 選單標題
     */
    private final int[] TAB_TITLES = new int[]{R.string.menu_msg, R.string.menu_contact, R.string.menu_find, R.string.menu_me};
    /**
     * 選單圖示
     */
    private final int[] TAB_IMGS = new int[]{R.drawable.tab_main_msg_selector, R.drawable.tab_main_contact_selector, R.drawable.tab_main_find_selector
            , R.drawable.tab_main_me_selector};

    @BindView(R.id.view_pager)
    ViewPager viewPager;
    @BindView(R.id.tab_layout)
    TabLayout tabLayout;

    /**
     * 頁卡介面卡
     */
    private PagerAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ButterKnife.bind(this);

        // 初始化頁卡
        initPager();

        setTabs(tabLayout, getLayoutInflater(), TAB_TITLES, TAB_IMGS);
    }

    /**
     * 設定頁卡顯示效果
     * @param tabLayout
     * @param inflater
     * @param tabTitlees
     * @param tabImgs
     */
    private void setTabs(TabLayout tabLayout, LayoutInflater inflater, int[] tabTitlees, int[] tabImgs) {
        for (int i = 0; i < tabImgs.length; i++) {
            TabLayout.Tab tab = tabLayout.newTab();
            View view = inflater.inflate(R.layout.item_main_menu, null);
            // 使用自定義檢視,目的是為了便於修改,也可使用自帶的檢視
            tab.setCustomView(view);

            TextView tvTitle = (TextView) view.findViewById(R.id.txt_tab);
            tvTitle.setText(tabTitlees[i]);
            ImageView imgTab = (ImageView) view.findViewById(R.id.img_tab);
            imgTab.setImageResource(tabImgs[i]);
            tabLayout.addTab(tab);
        }
    }

    private void initPager() {
        adapter = new MainFragmentAdapter(getSupportFragmentManager());
        viewPager.setAdapter(adapter);

        // 關聯切換
        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
        tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                // 取消平滑切換
                viewPager.setCurrentItem(tab.getPosition(), false);
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
    }

}

原始碼說明:

  • 繫結檢視物件使用到了ButterKnife框架;
  • viewPager和tabLayout添加了事件互相繫結,這樣viewPager的滑動和tab的切換都能相互影響;
  • setTabs方法設定tabLayout內部的具體內容,為介面中的TabLayout添加了四個子Tab檢視。
  • Tab的內容使用到了自定義檢視,比較靈活一點,也可以使用Tab自帶的佈局結構。

3、Tab自定義檢視item_main_menu.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:gravity="center_horizontal"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/img_tab"
        android:layout_width="24dip"
        android:layout_height="24dip"
        android:src="@drawable/menu_msg_default" />

    <TextView
        android:id="@+id/txt_tab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="2dip"
        android:text="首頁"
        android:textColor="@drawable/txt_main_menu_selector"
        android:textSize="11sp" />

</LinearLayout>

4、Tab圖示selector
以第一個Tab“微信”使用的圖示為例,tab_main_msg_selector.xml內容:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/menu_msg_selected" android:state_pressed="true" />
    <item android:drawable="@drawable/menu_msg_selected" android:state_selected="true" />
    <item android:drawable="@drawable/menu_msg_default" />
</selector>

使用到了兩張圖片:menu_msg_default、menu_msg_selected,一張預設圖樣式,一張選中圖樣式,對比如下:
menu_msg_default menu_msg_selected

5、Tab文字selector
因為Tab選中時需要做區分,所以文字顏色與圖示一起變動會更好看,文字顏色也需要寫selector。txt_main_menu_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/menu_green" android:state_selected="true"></item>
    <item android:color="@color/menu_gray"></item>
</selector>

menu_gray是預設狀態的灰色,menu_green是選中時呈現的綠色。

6、頁面切換Adapter

頁面切換內容由viewPager的adapter物件完成,使用Fragment作為子頁面時,adapter需要是FragmentPagerAdapter的例項,所以上述程式碼中的MainFragmentAdapter原始碼為:

package com.dommy.tab.adapter;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

import com.dommy.tab.fragment.ContactFragment;
import com.dommy.tab.fragment.FindFragment;
import com.dommy.tab.fragment.MeFragment;
import com.dommy.tab.fragment.MsgFragment;

/**
 * 主介面底部選單介面卡
 */
public class MainFragmentAdapter extends FragmentPagerAdapter {
    public MainFragmentAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int i) {
        Fragment fragment = null;
        switch (i) {
            case 0:
                fragment = new MsgFragment();
                break;
            case 1:
                fragment = new ContactFragment();
                break;
            case 2:
                fragment = new FindFragment();
                break;
            case 3:
                fragment = new MeFragment();
                break;
            default:
                break;
        }
        return fragment;
    }

    @Override
    public int getCount() {
        return 4;
    }

}

說明:

  • getItem返回具體位置的viewPager切換到i位置時對應的fragment,因為主框架的檢視是固定的,所以在這裡根據i的值返回對應的fragment物件即可;
  • getItem中返回的fragment也可以攜帶一些引數,如果需要的話;
  • getCount返回檢視的總數量,這裡是固定值4。

7、子頁面示例

本例中的子頁面只是呈現一個簡單的文字,實際開發中根據需要寫入相應佈局和功能替換即可。這裡以MeFragment作為示例:

MeFragment.java:

package com.dommy.tab.fragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.dommy.tab.R;

/**
 * 我
 */
public class MeFragment extends Fragment {

    public MeFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_me, container, false);
    }

}

fragment_me.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".fragment.MeFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="我" />

</RelativeLayout>

呈現效果:
我-介面效果

8、小結

MainActivity作為主框架,使用ViewPager實現4個子頁面Fragment的切換,使用TabLayout繫結ViewPager來切換檢視,實現了Tab卡切換、ViewPager滑動頁面的效果,基本實現了微信主框架的效果。

頂部導航條

TabLayout放在頂部的時候,加上一些屬性配置,就可以完美實現頂部導航的效果。根據導航條樣式,這裡分為三類:

  1. 自適應非固定條數形式;
  2. 居中固定條數形式;
  3. 平鋪固定條數形式。

現就三種效果分別展開,讀者可以根據需要選用相應的方法。

自適應非固定條數

這種就是和今日頭條類似的形式,適用於頂部選單數量不固定,而且比較多的情況。

從左至右依次排放,每個選單的內容均完全顯示,長度根據內容自動伸縮,超長後的選單需要滾動顯示。

看下效果:
自適應非固定條數

為了方便,原始碼寫在了MsgFragment中,也就是第一個子頁面“微信”中。
1、MsgFragment.java
佈局結構與MainActivity有類似之處。

package com.dommy.tab.fragment;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.dommy.tab.R;
import com.dommy.tab.adapter.MsgContentFragmentAdapter;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * 訊息
 * <p>在這個介面中實現類似今日頭條的頭部tab</p>
 */
public class MsgFragment extends Fragment {
    @BindView(R.id.tab_layout)
    TabLayout tabLayout;
    @BindView(R.id.view_pager)
    ViewPager viewPager;

    private MsgContentFragmentAdapter adapter;
    private List<String> names;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initData();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_msg, container, false);
        ButterKnife.bind(this, view);

        adapter = new MsgContentFragmentAdapter(getChildFragmentManager());
        viewPager.setAdapter(adapter);
        tabLayout.setupWithViewPager(viewPager);

        // 更新介面卡資料
        adapter.setList(names);
        return view;
    }

    private void initData() {
        names = new ArrayList<>();
        names.add("關注");
        names.add("推薦");
        names.add("熱點");
        names.add("視訊");
        names.add("小說");
        names.add("娛樂");
        names.add("問答");
        names.add("圖片");
        names.add("科技");
        names.add("懂車帝");
        names.add("體育");
        names.add("財經");
        names.add("軍事");
        names.add("國際");
        names.add("健康");
    }
}

2、fragment_msg.xml
佈局有主介面比較相似,不過TabLayout被放在頂部了。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".fragment.MsgFragment">

    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="34dip"
        app:tabBackground="@color/white"
        app:tabIndicatorColor="@color/menu_green"
        app:tabIndicatorHeight="1dip"
        app:tabMode="scrollable"
        app:tabMinWidth="40dip"
        app:tabPaddingStart="5dip"
        app:tabPaddingEnd="5dip"
        app:tabSelectedTextColor="@color/wx_head_selected"
        app:tabTextAppearance="@style/tab_head"
        app:tabTextColor="@color/wx_head_default" />

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dip"
        android:layout_weight="1"
        android:background="@color/white" />
</LinearLayout>

說明:

app:tabMode=“scrollable”

tabMode的值設為scrollable,表示tab卡過多時自動滑動。

3、MsgContentFragmentAdapter
因為內容頁大多近似,所以採用同一個Fragment佈局即可,內容根據傳參來修改。MsgContentFragmentAdapter.java:

package com.dommy.tab.adapter;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

import com.dommy.tab.fragment.MsgContentFragment;

import java.util.ArrayList;
import java.util.List;

/**
 * 訊息內容子頁面介面卡
 */
public class MsgContentFragmentAdapter extends FragmentPagerAdapter {
    private List<String> names;

    public MsgContentFragmentAdapter(FragmentManager fm) {
        super(fm);
        this.names = new ArrayList<>();
    }

    /**
     * 資料列表
     *
     * @param datas
     */
    public void setList(List<String> datas) {
        this.names.clear();
        this.names.addAll(datas);
        notifyDataSetChanged();
    }

    @Override
    public Fragment getItem(int position) {
        MsgContentFragment fragment = new MsgContentFragment();
        Bundle bundle = new Bundle();
        bundle.putString("name", names.get(position));
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public int getCount() {
        return names.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        String plateName = names.get(position);
        if (plateName == null) {
            plateName = "";
        } else if (plateName.length() > 15) {
            plateName = plateName.substring(0, 15) + "...";
        }
        return plateName;
    }
}

4、MsgContentFragment

子頁面只放了一個TextView用來顯示引數,MsgContentFragment.java:

package com.dommy.tab.fragment;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.dommy.tab.R;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * 訊息內容頁
 */
public class MsgContentFragment extends Fragment {
    @BindView(R.id.txt_content)
    TextView tvContent;

    private String name;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Bundle bundle = getArguments();
        name = bundle.getString("name");
        if (name == null) {
            name = "引數非法";
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_msg_content, container, false);
        ButterKnife.bind(this, view);

        tvContent.setText(name);
        return view;
    }

}

頁面佈局fragment_msg_content.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".fragment.MsgContentFragment">

    <TextView
        android:id="@+id/txt_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/hello_blank_fragment"
        android:textSize="18sp" />

</RelativeLayout>

居中固定條數

這種形式的導航欄位於水平居中位置,適用於頂部選單數量較少的情況。

從左至右依次排放,選單整體位於水平居中位置,因為數量較少,一般不會滾動顯示。

看下效果:
居中固定條數
由於介面構建原理與上述內容一致,在此僅說明不同之處:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".fragment.ContactFragment">

    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="34dip"
        android:background="@color/white"
        app:tabBackground="@color/white"
        app:tabGravity="center"
        app:tabIndicatorHeight="0dip"
        app:tabMinWidth="40dip"
        app:tabMode="fixed"
        app:tabPaddingEnd="5dip"
        app:tabPaddingStart="5dip"
        app:tabSelectedTextColor="@color/wx_head_selected"
        app:tabTextAppearance="@style/tab_head"
        app:tabTextColor="@color/wx_head_default" />

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dip"
        android:layout_weight="1"
        android:background="@color/white" />
</LinearLayout>

TabLayout有兩個屬性與“自適應非固定條數”形式不一樣:

app:tabMode=“fixed”

tabMode的值設定為fixed(預設值,也可以不加該屬性),表示TabLayout的內容最大長度不會超過自身長度,也就是說不會出現滾動條,新增這個屬性時,如果Tab過多,則會比較擠,出現Tab內部內容換行的情況。

app:tabGravity=“center”

tabGravity定義Tab內部的對齊方式,當該屬性值為center時,表示居中對齊,不進行拉伸,根據Tab內容自適應寬度。

平鋪固定條數

Tab平均分配寬度,適用於頂部選單數量固定,且需要撐滿頁面的情況。

從左至右依次排放,選單內容填滿整個TabLayout控制元件,不會滾動顯示。

看下效果:
平鋪固定條數

在此僅說明不同之處:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".fragment.FindFragment">

    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="34dip"
        android:background="@color/white"
        app:tabBackground="@color/white"
        app:tabGravity="fill"
        app:tabIndicatorHeight="0dip"
        app:tabMinWidth="40dip"
        app:tabMode="fixed"
        app:tabPaddingEnd="5dip"
        app:tabPaddingStart="5dip"
        app:tabSelectedTextColor="@color/wx_head_selected"
        app:tabTextAppearance="@style/tab_head"
        app:tabTextColor="@color/wx_head_default" />

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dip"
        android:layout_weight="1"
        android:background="@color/white" />
</LinearLayout>

TabLayout有一個屬性與“居中固定條數”形式不一樣:

app:tabGravity=“fill”

tabGravity定義Tab內部的對齊方式,當該屬性值為fill時,表示填充寬度,會進行拉伸,根據Tab數量平均分配每個Tab的寬度。

總結

TabLayout的出現基本解決了以前Android開發遇到的Tab頁卡效果不好、不流暢的問題,而且TabLayout還添加了Indicator,能夠隨手指滑動,修改起來也比較方便。

除了沒有直接解決滑動過程中顏色漸變、過渡的問題,普通場景使用TabLayout這個控制元件已經可以滿足需求了。

原始碼

相關推薦

Android仿底部選單+今日頭條頂部導航

背景 Android應用幾乎都會用到底部選單欄,在Material Design還沒有出來之前,TabHost等技術一直佔主流,現在Google新sdk中提供了TabLayout類可以便捷的做出底部選單欄效果。 本節我們實現兩種主要的Tab效果: 仿微信底部選

Android仿底部選單+頂部選單

        本文要實現仿微信微信底部選單欄+頂部選單欄,採用ViewPage來做,每一個page對應一個XML,當手指在ViewPage左右滑動時,就相應顯示不同的page(其實就是xml)並且同時改變底部選單按鈕的圖片變暗或變亮,同時如果點選底部選單按鈕,左

Android仿底部實現Tab選項卡切換效果

在網上看了比較多的關於Tab的教程,發現都很雜亂。比較多的用法是用TitlePagerTabStrip和ViewPaper。不過TitlePagerTabStrip有個很大的缺陷,Tab裡面的內容剛進去是沒有的,要滑一次才能加載出來。而且滑動的時候,Tab裡面的內容位置

Android仿今日頭條頂部導航效果

隨著時間的推移現在的軟體要求顯示的內容越來越多,所以要在小的螢幕上能夠更好的顯示更多的內容,首先我們會想到底部選單欄,但是有時候像今日頭條新聞客戶端要顯示的內容太多,而且又想在主介面全部顯示出來,所以有加了頂部導航欄。 今日頭條頂部導航欄區域的主要部分是一個導航選單。導航選

Android仿博、人人Feed詳情頁吸附導航

仿微博、人人的feed詳情頁面:Listview上下滑動,導航欄view可吸附在頂部的效果。 一、實現效果 上圖: 歡迎拍磚,拍拍更進步。 沒有對比,怎麼會有傷害,下面是 微博、人人的Feed詳情頁: 二、實現原理 1

仿今日頭條頂部導航效果實現

    最近在做一個專案的時候,需要實現像今天頭條那樣的頂部導航欄效果,通過在網上了解自定義View的相關知識和看別人的部落格,最終實現,本文既作為一個記錄(第一次寫部落格,寫得不好還請各位看官多多包涵),同時也給需要的人提供參考。    本文主要參考了鴻洋大神的部落格和風兮

Android專案導航仿底部導航TabLayout+ViewPager+Fragment

一、實現效果: 二、依賴jar包: compile 'com.android.support:design:24+'三、專案工程結構: 四、XML佈局 activity_main.xml佈局: <?xml version="1.0" encoding="u

Android仿qq及底部選單的幾種實現方式

最近專案沒那麼忙,想著開發app的話,有很多都是重複,既然是重複的,那就沒有必要每次都去寫,所以就想著寫一個app通用的基本框架,這裡說的框架不是什麼MVC,MVP,MVVM這種,而是app開發的通用模式,一般的app都是底部有幾個選單按鈕,類似qq這樣的,只不

Android 仿介面 使用RadioGroup+ViewPager實現底部按鈕切換以及滑動

先來效果圖哈哈 ![在這裡插入圖片描述](https://img-blog.csdn.net/2018100916182717?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjMwNjcwN

簡單的自定義BottomBar-仿底部導航

今天寫一個簡單的自定義的BottomBar。 圖片文字都是比較隨意的,具體實現中自己可以修改。下面是實現圖: 首先我們現在佈局中把想要顯示的整個介面的基本佈局搭建成功。(其實主要在於設定你的Tab。 如果專案中用到Bootmbar的地方比較多 或者是你想複用性高一點的話

html css 仿底部自定義選單

         最近幾個月一直從事微信開發,從剛開始的懵懂漸漸成長了一點。今天覺得微信底部自定義選單,如果能在html的頁面上也能顯示就好了. 記得以前看過某個網頁有類似效果.查找了該網頁的css.  ok現在html css 實現微信自定義選單效果. 不多說直接上程式碼

Android 仿通訊錄 導航分組列表-下】自定義View為RecyclerView打造右側索引導航IndexBar

本篇文章已授權微信公眾號 guolin_blog (郭霖)獨家釋出 一 概述 在上篇文章(http://blog.csdn.net/zxt0601/article/details/52355199)裡,我們用ItemDecoration為Recy

Android 仿調用第三方應用導航(百度,高德、騰訊)

detail decorview fcm onclick api 描述 log def repr 實現目標 先來一張微信功能截圖看看要做什麽 其實就是有一個目的地,點擊目的地的時候彈出可選擇的應用進行導航。 大腦動一下,要實現這個功能應該大體分成兩步: 底部彈出可選的地

android仿紅包動畫、Kotlin綜合應用、Xposed模塊、炫酷下拉視覺、UC瀏覽器滑動動畫等源碼

架構分析 body oot googl short html 博文 urn 管理 Android精選源碼 仿微信打開紅包旋轉動畫 使用Kotlin編寫的Android應用,內容你想象不到 Android手機上的免Root Android系統日誌Viewer 一個能讓微

android 仿表情雨下落!

block private www 事件觸發 dog ase 之間 apk ces 文章鏈接:https://mp.weixin.qq.com/s/yQXn-YjEFSW1X7A7CcuaVg 眾所周知,微信聊天中我們輸入一些關鍵詞會有表情雨下落,比如輸入「生日快樂」「

android仿、QQ等聊天介面,實現點選輸入框彈出軟鍵盤、點選其他區域收起軟鍵盤,預設滑動至最低端

如圖所示,點選輸入框及選擇圖片和傳送按鈕時軟鍵盤顯示且不消失,點選其他區域,則隱藏軟鍵盤。 主要程式碼如下: override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { if (ev!!.getAction() ==

asp.net 仿選單設定

第一步:新增引用檔案 <link rel="stylesheet" href="~/assets/css/bootstrap.min.css"> <link rel="stylesheet" href="~/assets/css/font-awesome.min.css"> <

Android 仿qq未讀訊息角標 BadgeView的使用

新增依賴: compile 'q.rorbin:badgeview:1.1.3' 使用方法: TextView textview = (TextView) findViewById(R.id.textview); new QBadgeView(this)

Android仿首頁下拉顯示小程式列表

花點時間重新熟悉一下AndroidUI方面的東西,把古董PullToRefreshView又擼了一遍,技術這種東西真是忘得快啊...在基礎上新增一點東西,粗糙地實現了仿微信首頁下拉顯示小程式列表的樣式,是的,粗糙粗糙... PullToRefreshView原始的實現思路: 1.垂直方向的L

Android仿右側頂部下拉對話方塊

我們使用微信都知道,其右側頂部有一個下拉對話方塊,我們可以執行新增好友,掃一掃等功能,今天我們就來模仿實現一下這個功能(實現的方式有很多種,我今天只說一種藉助透明主題Activity的方式實現);實現的效果如下: 下面就來說一說實現的思路(重要): 第一步:建立彈