前言
做了一個(gè)月的前端開(kāi)發(fā) 逐漸學(xué)習(xí)vue3+ts開(kāi)發(fā) 已經(jīng)可以正常寫(xiě)功能 只是有些原理還沒(méi)有搞懂!
說(shuō)起來(lái) 只要自己想學(xué)習(xí),其實(shí)也沒(méi)有那么難。畢竟TypeScript跟java太像了!
語(yǔ)法很像,都是面向?qū)ο笏枷耄?/p>
Android
由于項(xiàng)目緊急任務(wù) 需要在2個(gè)星期內(nèi)做一個(gè)平板端的操作app
領(lǐng)導(dǎo)又安排我回到了android崗位,話說(shuō)開(kāi)發(fā)是公司的一塊磚 哪里需要哪里搬 深有體會(huì)
兩個(gè)星期開(kāi)發(fā)一個(gè)app,時(shí)間上還是很趕的,由于和另外一個(gè)同事一起開(kāi)發(fā),壓力也沒(méi)那么大
三軍未動(dòng),糧草先行
雖然接口還沒(méi)有出來(lái),但UI已出,可以先工作了,不需要太大腦力勞動(dòng)的畫(huà)頁(yè)面操作,是每個(gè)android以及每個(gè)前端開(kāi)發(fā)工程師的基礎(chǔ)必備技能!
在和UI探討后,得到一個(gè)吸頂效果的需求,大概就是導(dǎo)航欄可以隨著滑動(dòng)改變位置。
這樣的需求也做過(guò)很多,2018年前后比較流行----------behavior
以前看過(guò)很多技術(shù)類(lèi)的博客 但是自己沒(méi)有記錄過(guò),雖然已經(jīng)是很舊的知識(shí)點(diǎn)了,這里再?gòu)?fù)習(xí)一下
Test效果圖

實(shí)現(xiàn)思路
其實(shí)不需要代碼輔助就可以完成上述的效果 這里指的是邏輯層的代碼
我們只需要再XML文件,完成合理的布局已經(jīng)屬性聲明 即可完成上述的效果
我這里運(yùn)用了 CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout+TabLayout+ViewPager
這一套組合
Coordinator在英文中是
協(xié)調(diào)的意思,所以我把CoordinatorLayout叫做協(xié)調(diào)者布局
AppBarLayout的直接子控件可以設(shè)置的屬性:layout_scrollFlags:
1.scroll|exitUntilCollapsed如果AppBarLayout的直接子控件設(shè)置該屬性,該子控件可以滾動(dòng),向上滾動(dòng)NestedScrollView出父布局(一般為CoordinatorLayout)時(shí),會(huì)折疊到頂端,向下滾動(dòng)時(shí)NestedScrollView必須滾動(dòng)到最上面的時(shí)候才能拉出該布局
2.scroll|enterAlways:只要向下滾動(dòng)該布局就會(huì)顯示出來(lái),只要向上滑動(dòng)該布局就會(huì)向上收縮
3.scroll|enterAlwaysCollapsed:向下滾動(dòng)NestedScrollView到最底端時(shí)該布局才會(huì)顯示出來(lái)
4.如果不設(shè)置改屬性,則改布局不能滑動(dòng)
CollapsingToolbarLayout:折疊的toolbar,它確實(shí)是起到折疊作用的,可以把自己的自布局折疊.
它的直接子布局可以使用的屬性:app:layout_collapseMode(折疊模式):可取的值如下:
1.pin:在滑動(dòng)過(guò)程中,此自布局會(huì)固定在它所在的位置不動(dòng),直到CollapsingToolbarLayout全部折疊或者全部展開(kāi)
2.parallax:視察效果,在滑動(dòng)過(guò)程中,不管上滑還是下滑都會(huì)有視察效果,不知道什么事視察效果自己看gif圖(layout_collapseParallaxMultiplier視差因子 0~1之間取值,當(dāng)設(shè)置了parallax時(shí)可以配合這個(gè)屬性使用,調(diào)節(jié)自己想要的視差效果)
3.不設(shè)置:跟隨NestedScrollView的滑動(dòng)一起滑動(dòng),NestedScrollView滑動(dòng)多少距離他就會(huì)跟著走多少距離
TabLayout 是一個(gè)選項(xiàng)卡布局 一般和ViewPager配合使用 一遍達(dá)到聯(lián)動(dòng)的效果 跟著滑動(dòng)
ViewPager 視圖滑動(dòng)切換組件 和TabLayout組合可以達(dá)到兩者聯(lián)動(dòng)效果 當(dāng)然自己也可以獨(dú)立使用
上面這2個(gè)都是android應(yīng)用開(kāi)發(fā)經(jīng)常用到的組件
XML代碼布局
仔細(xì)觀察下面xml布局,用到了2個(gè)關(guān)鍵屬性
第一個(gè)屬性 layout_scrollFlags
CollapsingToolbarLayout的
app:layout_scrollFlags="exitUntilCollapsed|scroll"
當(dāng)ScrollView將要向下滾動(dòng)的時(shí)候,優(yōu)先滾動(dòng)的是自己,當(dāng)自己滾動(dòng)到頂部頭的時(shí)候,再開(kāi)始觸發(fā)滾動(dòng)
1:AppBarLayoout中的childView;
這和單純使用scroll的效果是一致的;
2:當(dāng)Scrollview將要向上滾動(dòng)的時(shí)候,優(yōu)先將AppBarLayout中的childView滾動(dòng)至最小高度,然后scrollview才開(kāi)始滾動(dòng)。
第二個(gè)屬性 layout_behavior
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android 系統(tǒng)層的滾動(dòng)屬性,沒(méi)有設(shè)置的話, AppbarLayout將不會(huì)響應(yīng)滾動(dòng)布局的滾動(dòng)事件.
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:fitsSystemWindows="true"
android:orientation="vertical"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/coll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#2196F3"
android:fitsSystemWindows="true"
app:layout_scrollFlags="exitUntilCollapsed|scroll">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/ic_launcher_background" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="20dp"
android:text="我是內(nèi)容1"
android:textColor="#fff"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="20dp"
android:text="我是內(nèi)容2"
android:textColor="#fff"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="20dp"
android:text="我是內(nèi)容3"
android:textColor="#fff"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="20dp"
android:text="我是內(nèi)容4"
android:textColor="#fff"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="20dp"
android:text="我是內(nèi)容5"
android:textColor="#fff"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="20dp"
android:text="我是內(nèi)容6"
android:textColor="#fff"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="20dp"
android:text="我是內(nèi)容7"
android:textColor="#fff"
android:textSize="20sp" />
</LinearLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="70dp"
android:background="#FFF"
app:tabIndicatorColor="@android:color/holo_blue_dark"
app:tabSelectedTextColor="@color/purple_200"
app:tabTextColor="#000" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
數(shù)據(jù)層代碼
Activity
public class MainActivity extends AppCompatActivity {
private final List<Fragment> list = new ArrayList<>();
private final List<String> title = new ArrayList<>();
CollapsingToolbarLayout collapsingToolbarLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabLayout tabLayout = findViewById(R.id.tablayout);
ViewPager viewPager = findViewById(R.id.viewpager);
collapsingToolbarLayout = findViewById(R.id.coll);
title.add("Tab1");
title.add("Tab2");
OneFragment oneFragment = new OneFragment();
TwoFragment twoFragment = new TwoFragment();
list.add(oneFragment);
list.add(twoFragment);
collapsingToolbarLayout.setTitle("我是返回");
viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
@NonNull
@Override
public Fragment getItem(int position) {
return list.get(position);
}
@Override
public int getCount() {
return list.size();
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return title.get(position);
}
});
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
tabLayout.setupWithViewPager(viewPager);
tabLayout.setTabMode(TabLayout.MODE_FIXED);
}
}
Fragment
public class OneFragment extends Fragment {
private final List<String> stringList = new ArrayList<>();
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_one, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//數(shù)據(jù)
initString();
RecyclerView recyclerView = view.findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
TextAdapter adapter = new TextAdapter(stringList);
recyclerView.setAdapter(adapter);
}
private void initString() {
for (int i = 0; i < 20; i++) {
stringList.add("0");
stringList.add("1");
stringList.add("2");
stringList.add("3");
stringList.add("4");
}
}
}
Adapter
public class TextAdapter extends RecyclerView.Adapter<TextAdapter.ViewHolder> {
private final List<String> stringList;
public TextAdapter(List<String> list) {
stringList = list;
}
static class ViewHolder extends RecyclerView.ViewHolder {
Button mButton;
public static int anInt = 0;
public ViewHolder(View view) {
super(view);
mButton = view.findViewById(R.id.item_btn);
anInt++;
}
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_text_type, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
//綁定子view事件
holder.mButton.setText(String.format("我是Item %s",position));
}
@Override
public int getItemCount() {
return stringList.size();
}
@Override
public int getItemViewType(int position) {
return -1;
}
}
布局就不貼了 一個(gè)是recyclerView 一個(gè)是Item
效果圖
另外附一張項(xiàng)目中的效果圖 實(shí)現(xiàn)原理差不多
