中学网站模板下载seo实战视频
在新闻资讯 APP 底部切换不同类型界面,部分界面可以通过 ViewPager 实现滑动切换
因为这个项目的编写顺序有问题,先写了顶部后写底部导致了今天浪费很多时间在改代码,看来安卓开发的顺序还是很重要的,活动和碎片,碎片和碎片都可以有很多嵌套关系。
总结一下目前的开发进度:
介绍一下我的开发流程把:
首先新建一个项目,在mainactivity中我们知道,搜索框不论在哪一个碎片都是在的,所以我们直接在activity_main.xml写进去,同时bottom的菜单栏也是不变的,所以我们把他也设置一下,以下是完整代码
activity_main.xml
<?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:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".activity.MainActivity"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:background="#D3D3D3"android:padding="8dp"android:elevation="2dp"><EditTextandroid:id="@+id/search_edit_frame"android:layout_width="0dp"android:layout_height="40dp"android:layout_weight="3"android:background="@drawable/search_bg"android:paddingHorizontal="12dp"android:singleLine="true" /><Buttonandroid:id="@+id/button"android:layout_width="0dp"android:layout_height="40dp"android:layout_weight="1"android:text="搜索"android:backgroundTint="#4CAF50"android:textColor="@android:color/white" /></LinearLayout><FrameLayoutandroid:id="@+id/fragment_container"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="8dp"android:background="#FFFFFF"android:layout_gravity="bottom" ><!-- 首页 --><LinearLayoutandroid:id="@+id/home_tab"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="vertical"android:gravity="center"><ImageViewandroid:layout_width="25dp"android:layout_height="25dp"android:layout_gravity="center_horizontal"android:src="@drawable/main"android:contentDescription="首页图标"/><TextViewandroid:id="@+id/home_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16dp"android:text="首页"android:gravity="center_horizontal"/></LinearLayout><!-- 菜单 --><LinearLayoutandroid:id="@+id/menu_tab"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="vertical"android:gravity="center"><ImageViewandroid:layout_width="25dp"android:layout_height="25dp"android:layout_gravity="center_horizontal"android:src="@drawable/menu"android:contentDescription="菜单图标"/><TextViewandroid:id="@+id/menu_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16dp"android:text="菜单"android:gravity="center_horizontal"/></LinearLayout><!-- 我的 --><LinearLayoutandroid:id="@+id/mine_tab"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="vertical"android:gravity="center"><ImageViewandroid:layout_width="25dp"android:layout_height="25dp"android:layout_gravity="center_horizontal"android:src="@drawable/mine"android:contentDescription="我的图标"/><TextViewandroid:id="@+id/mine_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16dp"android:text="我的"android:gravity="center_horizontal"/></LinearLayout></LinearLayout></LinearLayout>
mainActivity
package com.example.eznews.activity;import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.TextView;import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;import com.example.eznews.R;
import com.example.eznews.fragment.HomeFragment;
import com.example.eznews.fragment.MenuFragment;
import com.example.eznews.fragment.MineFragment;public class MainActivity extends AppCompatActivity {private LinearLayout homeTab, menuTab, mineTab;private int currentTab = R.id.home_tab;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new HomeFragment()).commit();initTab();// 初始化时设置首页背景色homeTab.setBackgroundColor(Color.GRAY);}private void initTab() {homeTab = findViewById(R.id.home_tab);menuTab = findViewById(R.id.menu_tab);mineTab = findViewById(R.id.mine_tab);homeTab.setOnClickListener(v -> switchFragment(R.id.home_tab));menuTab.setOnClickListener(v -> switchFragment(R.id.menu_tab));mineTab.setOnClickListener(v -> switchFragment(R.id.mine_tab));}private void animateTabSelection(View view) {// 加载动画资源Animation scaleDown = AnimationUtils.loadAnimation(this, R.anim.scale_down);Animation scaleUp = AnimationUtils.loadAnimation(this, R.anim.scale_up);Animation bounceBack = AnimationUtils.loadAnimation(this, R.anim.bounce_back);// 设置动画监听器,实现连续播放scaleDown.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {view.startAnimation(scaleUp);}@Overridepublic void onAnimationRepeat(Animation animation) {}});scaleUp.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {view.startAnimation(bounceBack);}@Overridepublic void onAnimationRepeat(Animation animation) {}});bounceBack.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {clearAllTabBackground();view.setBackgroundColor(Color.GRAY);}@Overridepublic void onAnimationEnd(Animation animation) {// 动画结束后设置背景色}@Overridepublic void onAnimationRepeat(Animation animation) {}});// 开始执行动画view.startAnimation(scaleDown);}private void clearAllTabBackground() {homeTab.setBackgroundColor(Color.TRANSPARENT);menuTab.setBackgroundColor(Color.TRANSPARENT);mineTab.setBackgroundColor(Color.TRANSPARENT);}private void switchFragment(int tabId) {if (currentTab == tabId) {return;}currentTab = tabId;animateTabSelection(findViewById(tabId));// 使用 if-else 替代 switch 语句if (tabId == R.id.home_tab) {getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new HomeFragment()).commit();} else if (tabId == R.id.menu_tab) {getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MenuFragment()).commit();} else if (tabId == R.id.mine_tab) {getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MineFragment()).commit();}}
}
这里的mainActivity的代码只有很小一段
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new HomeFragment()).commit();
是需要了解一下的,其他的动画什么的就不多说了
动态显示Fragment要使用FrameLayout
这里简单看下菜单和我的碎片
package com.example.eznews.fragment;//我的Fragmentimport android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;public class MineFragment extends Fragment {@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {TextView view = (TextView) View.inflate(getActivity(), android.R.layout.simple_list_item_1, null);view.setText("这是个人中心页面的碎片布局");view.setBackgroundColor(Color.YELLOW);return view;}
}
package com.example.eznews.fragment;//菜单Fragmentimport android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;public class MenuFragment extends Fragment {@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {TextView view = (TextView) View.inflate(getActivity(), android.R.layout.simple_list_item_1, null);view.setText("这是菜单的碎片布局");view.setBackgroundColor(Color.YELLOW);return view;}
}
没什么好说的动态设置了一下背景和文字没有UI(后续会补上)因为目前再学习ViewPage和Fragment的页面切换
主要看主页的代码和布局
fragment_home.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:app="http://schemas.android.com/apk/res-auto"><LinearLayoutandroid:id="@+id/category_bar"android:layout_width="match_parent"android:layout_height="50dp"android:orientation="horizontal"android:background="@android:color/white"android:elevation="1dp"app:layout_behavior=".util.ScrollAwareFABBehavior"><TextViewandroid:id="@+id/tab_hot"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:text="热榜"android:textSize="16sp"android:textColor="#333333"android:gravity="center"android:clickable="true"android:background="?attr/selectableItemBackground" /><TextViewandroid:id="@+id/tab_follow"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:text="关注"android:textSize="16sp"android:textColor="#333333"android:gravity="center"android:clickable="true"android:background="?attr/selectableItemBackground" /><TextViewandroid:id="@+id/tab_recommend"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:text="推荐"android:textSize="16sp"android:textColor="#333333"android:gravity="center"android:clickable="true"android:background="?attr/selectableItemBackground" /><TextViewandroid:id="@+id/tab_city"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:text="同城"android:textSize="16sp"android:textColor="#333333"android:gravity="center"android:clickable="true"android:background="?attr/selectableItemBackground" /></LinearLayout><!-- ViewPager2容器 --><androidx.viewpager2.widget.ViewPager2android:id="@+id/view_pager"android:layout_width="match_parent"android:layout_height="match_parent"/></androidx.coordinatorlayout.widget.CoordinatorLayout>
先看下xml,因为要实现下滑拉出上滑收起的分类栏,所以这个fragment要使用coordinator布局,并且设置一个behavior,同时要实现左右滑切换分类栏,所以我加入一个ViewPage2
再来看一下代码
HomeFragment
package com.example.eznews.fragment;import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.widget.ViewPager2;import com.example.eznews.R;
import com.example.eznews.adapter.CategoryPagerAdapter;public class HomeFragment extends Fragment {private ViewPager2 viewPager;private TextView tabHot, tabFollow, tabRecommend, tabCity;private int selectedTab = 0;@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {super.onCreateView(inflater, container, savedInstanceState);// 加载布局文件View view = inflater.inflate(R.layout.fragment_home, container, false);// 初始化ViewPager2viewPager = view.findViewById(R.id.view_pager);CategoryPagerAdapter adapter = new CategoryPagerAdapter(requireActivity());viewPager.setAdapter(adapter);viewPager.setOffscreenPageLimit(4); // 预加载4个页面viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {@Overridepublic void onPageSelected(int position) {super.onPageSelected(position);updateTabSelection(position);}});// 传入 view 对象初始化标签initCategoryTabs(view);return view;}private void initCategoryTabs(View view) {// 从 view 对象中查找 TextViewtabHot = view.findViewById(R.id.tab_hot);tabFollow = view.findViewById(R.id.tab_follow);tabRecommend = view.findViewById(R.id.tab_recommend);tabCity = view.findViewById(R.id.tab_city);// 设置标签点击事件if (tabHot != null) {tabHot.setOnClickListener(v -> viewPager.setCurrentItem(0));}if (tabFollow != null) {tabFollow.setOnClickListener(v -> viewPager.setCurrentItem(1));}if (tabRecommend != null) {tabRecommend.setOnClickListener(v -> viewPager.setCurrentItem(2));}if (tabCity != null) {tabCity.setOnClickListener(v -> viewPager.setCurrentItem(3));}// 默认选中第一个标签updateTabSelection(0);}private void updateTabSelection(int position) {// 重置所有标签样式resetAllTabs();// 根据选中位置设置标签样式TextView[] tabs = {tabHot, tabFollow, tabRecommend, tabCity};if (position >= 0 && position < tabs.length && tabs[position] != null) {tabs[position].setTextColor(Color.RED);tabs[position].setBackgroundColor(Color.LTGRAY);}}private void resetAllTabs() {TextView[] tabs = {tabHot, tabFollow, tabRecommend, tabCity};for (TextView tab : tabs) {if (tab != null) {tab.setTextColor(Color.BLACK);tab.setBackgroundColor(Color.TRANSPARENT);}}}
}
```
可以细节了解一下viewPage是怎么玩的,首先他跟ListView有点像,需要一个adapter来关联ViewPage和各个碎片,所以代码里面先创建一个viewPage实例,然后重写ViewPageAdapter的代码重点就是onCreate返回你自己想要的页面
@NonNull@Overridepublic Fragment createFragment(int position) {switch (position) {case 0:return new HotFragment();case 1:return new FollowFragment();case 2:return new RecommendFragment();case 3:return new CityFragment();default:throw new IllegalArgumentException("Invalid position: " + position);}}
这是完整代码
package com.example.eznews.adapter;import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;import com.example.eznews.fragment.fragment2.CityFragment;
import com.example.eznews.fragment.fragment2.FollowFragment;
import com.example.eznews.fragment.fragment2.HotFragment;
import com.example.eznews.fragment.fragment2.RecommendFragment;public class CategoryPagerAdapter extends FragmentStateAdapter {public CategoryPagerAdapter(@NonNull FragmentActivity fragmentActivity) {super(fragmentActivity);}@NonNull@Overridepublic Fragment createFragment(int position) {switch (position) {case 0:return new HotFragment();case 1:return new FollowFragment();case 2:return new RecommendFragment();case 3:return new CityFragment();default:throw new IllegalArgumentException("Invalid position: " + position);}}@Overridepublic int getItemCount() {return 4; // 四个分类页面}
}
主要是homeFragment的代码需要好好理解一下
下面就不多说了,各个fragment里面的小布局recyclerView,包括很多的控件都已经玩过了稍微搞一下时间就可以写出来,我就不贴代码了这里。