实现功能:从activity布局到fragment布局,再到recycler布局,以及viewpager布局
一 . 难点/知识点:
1.recycler适配 直接看 三.3
2.pagerview 直接看 三.4
因为过多的布局文件 应该一边看代码,一边看相对应的xml和id.
二. 流程图/运行图:
1. 代码图
2. 布局图:
3. 运行图:
a. 打开应用,recycler list all fragment instance
b. 点击一个item,打开pagerview 再加载itemFragmemt
c. 左右滑动 可以滑动到其他item里面。
4.流程图:
a.整体activity fragment和对应xml文件
b.数据 item 和itemLab
三. 实现代码
写在前面,每个人的数据模型不一样,我使用的item和itemLab类在文末,对于数据这个没有重点描述,看看应该都能懂。所有代码都有,但是图方便和正确率可以直接clone我的git仓库代码。
star 我的项目,我会不断更新内容,更多基础demo,
项目地址:link
1.singleActivity
1.2.3.一起食用更容易理解
public abstract class SingleFragmentActivity extends AppCompatActivity {
protected abstract Fragment createFragment();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.fragment_container, createFragment());
transaction.commit();
}
}
再看布局文件:activity_fragment.xml
<FrameLayout
android:id="@+id/fragment_container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
2.ItemListActivity 继承 SingleActivity
无对应布局文件
public class ItemsListActivity extends SingleFragmentActivity {
@Override
protected Fragment createFragment(){
return ItemsListFragment.newInstance();
}
}
继承 重写singleActivity虚方法,返回给singleActivity一个碎片。
3.itemListFragment 返回的正是这个碎片类
先看2. return newInstance返回的是个什么玩意儿, 先创建了该类,再返回该类 很简单
public static ItemsListFragment newInstance(){
return new ItemsListFragment();
}
好,再看全部代码,再分析recycler
public class ItemsListFragment extends Fragment {
public Toolbar mToolbar;
private EditText mEditText;
private RecyclerView mRecyclerView;
private ItemAdapter mAdapter;
public static ItemsListFragment newInstance(){
return new ItemsListFragment();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_itemlist_recycler, container, false);//碎片视图
mRecyclerView=(RecyclerView)v.findViewById(R.id.item_recycler_view);//recycler视图
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
upDateUI();
return v;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
private class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TextView mTitleTextView;
private TextView mDateTextView;
private Item mitem;
public ItemHolder(LayoutInflater inflater , ViewGroup parent){
super(inflater.inflate(R.layout.fragment_list_xxxcontent,parent,false));//content视图
itemView.setOnClickListener(this);
mTitleTextView=(TextView)itemView.findViewById(R.id.item_title_list);
mDateTextView=(TextView)itemView.findViewById(R.id.item_data_list);
}
public void bind(Item item){
mitem=item;
mTitleTextView.setText(mitem.getmTitle());
mDateTextView.setText(mitem.getmData().toString());
}
@Override
public void onClick(View view){
Toast.makeText(getActivity(),mitem.getmTitle()+"cliced",Toast.LENGTH_LONG).show();
Intent intent=ItemPagerActivity.newInstance(getActivity(),mitem.getmId());
startActivity(intent);
}
}
private class ItemAdapter extends RecyclerView.Adapter<ItemHolder>{
private List<Item>mItems;
public ItemAdapter(List<Item>items){
mItems=items;
}
@NonNull
@Override
public ItemHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater=LayoutInflater.from(getActivity());
return new ItemHolder(layoutInflater,parent);
}
@Override
public void onBindViewHolder(@NonNull ItemHolder holder, int position) {
Item item=mItems.get(position);
holder.bind(item);
}
@Override
public int getItemCount() {
return mItems.size();
}
}
private void upDateUI(){
ItemLab itemLab=ItemLab.get(getActivity());
List<Item>items=itemLab.getmItems();
if (mAdapter==null){
mAdapter=new ItemAdapter(items);
mRecyclerView.setAdapter(mAdapter);}
else {mAdapter.notifyDataSetChanged();}
}
}
再看对应的布局文件: a. recycler所在碎片fragment_itemlist_recycler.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
布局:b. recycler作为容器 里面每个内容的布局:fragment_list_xxxcontent.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<TextView
android:id="@+id/item_title_list"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="item_title"/>
<TextView
android:id="@+id/item_data_list"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="item_data"/>
</androidx.appcompat.widget.LinearLayoutCompat>
大篇幅都是关于recycler的,这也是recycler实现代码,主要函数有 itemHolder继承重写,itemAdapter< ItemHolder>重写继承,以及更新ui的upDateUI()
a. 看程序运行流程,运行upDateUI(),先new Adapter,再调用setAdapter
mAdapter=new ItemAdapter(items);
mRecyclerView.setAdapter(mAdapter);
b.在class ItemAdapter先调用getItemCount(),反馈给RecyclerView有多少个对象。
@Override
public int getItemCount() {
return mItems.size();
}
c.然后调用class ItemAdapter里面的onCreateViewHolder()。
@Override
public ItemHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater=LayoutInflater.from(getActivity());
return new ItemHolder(layoutInflater,parent);
}
d.在c中会返回一个ItemHolder(子视图),ItemHolder构造函数就只容纳view视图,它会启用这个布局fragment_list_xxxcontent.xml,并找到里面的两个textview,
public ItemHolder(LayoutInflater inflater , ViewGroup parent){
super(inflater.inflate(R.layout.fragment_list_xxxcontent,parent,false));//content视图
itemView.setOnClickListener(this);
mTitleTextView=(TextView)itemView.findViewById(R.id.item_title_list);
mDateTextView=(TextView)itemView.findViewById(R.id.item_data_list);
}
e. 再回到class ItemAdaper里面,调用onBindViewHolder()。
@Override
public void onBindViewHolder(@NonNull ItemHolder holder, int position) {
Item item=mItems.get(position);
holder.bind(item);
}
f. e中会调用class holder的bind()函数负责数据绑定,到此,一个子视图就完成了,再创建下一个View就是重复c-d-e-f过程。
public void bind(Item item){
mitem=item;
mTitleTextView.setText(mitem.getmTitle());
mDateTextView.setText(mitem.getmData().toString());
}
g. 既然holder提供视图,我们设置implement View.OnClickListener,再重写监听事件,就能完成点击每个子项发出动作,例如查看详情。
@Override
public void onClick(View view){
Toast.makeText(getActivity(),mitem.getmTitle()+"cliced",Toast.LENGTH_LONG).show();
Intent intent=ItemPagerActivity.newInstance(getActivity(),mitem.getmId());
startActivity(intent);
}
到此Recycler使用方法结束
4. 在3.itemListFragment中我们设置了监听,现在再来看一下,
Intent intent=ItemPagerActivity.newInstance(getActivity(),mitem.getmId());
startActivity(intent);
我们使用intent打开了一个新的activity->ItemPagerActivity,传入了item的UUID,方便FragmentStatePagerAdapter定位到具体哪个item。
itempagerActivity类代码如下,
public class ItemPagerActivity extends AppCompatActivity {
private ViewPager mViewPager;
private List<Item>mItems; //
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_pager);
UUID itemid = (UUID) getIntent().getSerializableExtra("itemid"); //
mViewPager = (ViewPager) findViewById(R.id.activity_item_view_pager);
mItems = ItemLab.get(this).getmItems();
FragmentManager fragmentManager = getSupportFragmentManager();
mViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager) {
@Override
public Fragment getItem(int position) {
Item item = mItems.get(position);
return ItemFragment.newInstance(item.getmId());
}
@Override
public int getCount() {
return mItems.size();
}
});
for (int i = 0; i < mItems.size(); i++) {
if (mItems.get(i).getmId().equals(itemid)) {
mViewPager.setCurrentItem(i);
break;
}
}
}
public static Intent newInstance(Context packageContenxt, UUID itemId){
Intent intent=new Intent(packageContenxt,ItemPagerActivity.class);
intent.putExtra("itemid",itemId);
return intent;
}
}
对应布局:activity_item_pager.xml :
<androidx.viewpager.widget.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/activity_item_view_pager">
</androidx.viewpager.widget.ViewPager>
重点讲解 三个点:mViewPager.setAdapter的getcount(),
getitem(int position)和一个for()循环。
a. getIcount()返回Int类型,告诉有多少个对象,
b. getItem(int posintion)函数代码如下:
Item item = mItems.get(position);
return ItemFragment.newInstance(item.getmId());
这里获得一个item,并产生了一个碎片,(viewpager是该碎片的容器)
c. for()循环是由3.g中 我们点击了哪个子视图,然后传过来的参数,我们用for循环遍历Items.找到它,getItem(int position)就找到该使用具体哪个item,ItemFragment就能显示对应item的数据。
5.ItemFragment类
现在我们看来看该类,该类是由4.b触发产生的碎片,很简单,配合一个布局,将item.title和item.content放在viewpager容器里面。ps:可以改写item数据。
ItemFragment代码:
public class ItemFragment extends Fragment {
private Item mitem;
private EditText mtitle;
private EditText mdate;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_item_dital, container, false);//碎片视图
mtitle=(EditText)v.findViewById(R.id.item_title);
mdate=(EditText)v.findViewById(R.id.item_data);
mtitle.setText(mitem.getmTitle());
return v;
}
public static ItemFragment newInstance(UUID itemid){
Bundle args=new Bundle();
args.putSerializable("itemid",itemid);
ItemFragment fragment =new ItemFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UUID itemId=(UUID)getArguments().getSerializable("itemid");
mitem=ItemLab.get(getActivity()).getItem(itemId);
}
@Override
public void onPause(){
super.onPause();
mitem.setmTitle(mtitle.getText().toString());
}
}
fragment_item_dital.xml布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<EditText
android:id="@+id/item_title"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="item_title"/>
<EditText
android:id="@+id/item_data"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="item_data"/>
</androidx.appcompat.widget.LinearLayoutCompat>
到此viewpager功能实现,可以左右滑动,查看不同item.
最后贴上item和itemLab类代码:
public class Item {
public boolean ismSoved() {
return mSoved;
}
public void setmSoved(boolean mSoved) {
this.mSoved = mSoved;
}
public Date getmData() {
return mData;
}
public void setmData(Date mData) {
this.mData = mData;
}
public UUID getmId() {
return mId;
}
public void setmId(UUID mId) {
this.mId = mId;
}
private UUID mId;
public String getmTitle() {
return mTitle;
}
public void setmTitle(String mTitle) {
this.mTitle = mTitle;
}
private String mTitle;
private Date mData;
private boolean mSoved;
public Item(){
mId=UUID.randomUUID();
mData=new Date();
}
}
public class ItemLab {
private static ItemLab sItemLab;
private List<Item>mItems;
public static ItemLab get(Context context){
if(sItemLab==null){
sItemLab=new ItemLab(context);
}
return sItemLab;
}
private ItemLab(Context context){
mItems=new ArrayList<>();
for(int i=0;i<100;i++){
Item item=new Item();
item.setmTitle("items "+i);
item.setmSoved(i%2==0);
mItems.add(item);
}
}
public List<Item>getmItems(){
return mItems;
}
public Item getItem(UUID id){
for(Item item:mItems){
if(item.getmId().equals(id)){
return item;
}
}
return null;
}
}
四.结尾
终于写完了,第一次写长篇博客,花了两三个小时,本人也是初学安卓开发,很多不对的地方请前辈指正,feel free to ask me about this blog,求关注博主,持续更新更多安卓基础demo,一起进步。 我的github项目在这里:https://github.com/easyasd/android-learning-demo-collections Star it 吧