Android Fragment實現分屏


在項目中碰到一個問題,新開發一個平板APP,項目要求是把原來的一個手機端APP放在項目左側顯示,右側添加新加的功能。

首先想到了Fragment,以前做過Fragment的一些簡單的Demo,但是都沒有應用到項目中去過,這次倒是好好的運用了一把。

首先,考慮到已經存在的手機端APP代碼繁多,且不怎么規范(代碼里面大概有二三十個Activity文件,且命名及其他方面都極其不規范),所以就想不要在原來代碼上太多的重構,在看了一篇文章之后,慢慢的有了些思路。(http://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=404548816&idx=1&sn=f042037982ed2e74210c57edf864e31a&scene=0#wechat_redirect)這篇文章也說了些重構的問題,不過看了之后覺得不適合自己的,只是很好的為自己提供了一個思路。於是就自己寫了個Demo。

Demo的結構是這樣的

我先寫了一個BasePadFragment,讓所有的Fragment去實現這個基類,從而統一實現一些共通的方法。由於是Demo所以基類里面只提供了一個Fragment的跳轉方法

BasePadFragment.java

import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

import java.util.List;

/**
 * Created by Bob on 2016/4/11.
 */
public class BasePadFragment extends Fragment{

    public Context mContext;

    public void startToFragment(Context context,int container,Fragment newFragment){

        FragmentManager manager = getFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(container,newFragment);
        transaction.addToBackStack(context.getClass().getName());
        transaction.commit();
    }

}

方法里面的參數分別是context:上下文;container:Fragment的容器;newFragment:要跳轉到的Fragment的對象;

再看看方法體里面,首先獲得Frament的一些主要操作對象FragmentManager/FragmentTransaction然后利用transaction進行fragment的置換,再將當前fragment進行壓棧操作,這一步非常關鍵,因為如果不添加的話,按返回按鈕是不能回到上一個fragment的。最后是提交commit方法。

主界面activity比較簡單就是簡單的一個onCreatView再后面的源碼里面可以查看。

再來說主界面的布局:

activity_index.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:baselineAligned="false">

    <FrameLayout
        android:id="@+id/layout_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="4">

        <fragment
            android:id="@+id/left_fragment"
            android:name="com.sailing.www.multiscreendemo.fragment.LeftFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>

    <View
        android:layout_width="5dp"
        android:layout_height="match_parent"
        android:background="#000000" />

    <FrameLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="6">

        <fragment
            android:id="@+id/right_fragment"
            android:name="com.sailing.www.multiscreendemo.fragment.RightFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>
</LinearLayout>

   可以看到我在主界面里面添加了兩個fragment;將這兩個fragment水平的放在一個LinearLayout里面。在放入的時候切記要將fragment外面包裹一層parentView我用的是FrameLayout,因為在跳轉的時候要針對container進行跳轉,所以要在這個parentView就相當於是一個容器將fragment放在里面,所有的頁面的替換都是在這個容器內進行操作。且這個容器一定要添加id,否則會報找不到view的錯誤。

界面效果是這樣的。

左側的Fragment 

LeftFramgment:

import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

/**
 * Created by Bob on 2016/4/5.
 */
public class LeftFragment extends BasePadFragment implements View.OnClickListener{

    private Button btnNextPage,btnNextAnother;
    private RecyclerView mRecyclerView;
    private HorizontalListAdapter horizontalListAdapter;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.layout_left, null);
        btnNextPage = (Button)view.findViewById(R.id.btn_next_page);
        btnNextAnother = (Button)view.findViewById(R.id.btn_next_another);
        btnNextPage.setOnClickListener(this);
        btnNextAnother.setOnClickListener(this);

        mRecyclerView = (RecyclerView)view.findViewById(R.id.recycler_view);

        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        // 設置布局管理器
        mRecyclerView.setLayoutManager(layoutManager);

        String[] dataset = new String[100];
        for (int i = 0; i < dataset.length; i++) {
            dataset[i] = "item" + i;
        }
        RecyclerAdapter mAdapter = new RecyclerAdapter(dataset);
        mRecyclerView.setAdapter(mAdapter);
        return view;
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_next_page:
                AnotherFragment anotherFragment  = new AnotherFragment();
                startToFragment(getActivity(), R.id.layout_container, anotherFragment);
                break;
            case R.id.btn_next_another:
                NextAnotherFragment nextAnotherFragment = new NextAnotherFragment();
                startToFragment(getActivity(),R.id.layout_container,nextAnotherFragment);
                break;
            default:
                break;
        }
    }


    public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
        private String[] mDataset;

      
        public RecyclerAdapter(String[] dataset) {
            mDataset = dataset;
        }

        public  class ViewHolder extends RecyclerView.ViewHolder {

            public TextView mTextView;

           
            public ViewHolder(View itemView) {
                super(itemView);
                mTextView = (TextView) itemView;
            }
        }

     
        @Override
        public int getItemCount() {
            return mDataset.length;
        }

      android.support.v7.widget.RecyclerView.Adapter#onBindViewHolder(android.support.v7.widget.RecyclerView.ViewHolder,
         *      int)
         */
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            holder.mTextView.setText(mDataset[position]);
        }

      android.support.v7.widget.RecyclerView.Adapter#onCreateViewHolder(android.view.ViewGroup,
         *      int)
         */
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = View.inflate(parent.getContext(),
                    android.R.layout.simple_list_item_1, null);
            ViewHolder holder = new ViewHolder(view);
            return holder;
        }
    }
}

 因為后續還在這個Demo里面進行了另外一些測試,所以有一些雜的控件在里面。我們只看代碼的主要模塊,就是按鈕的操作,在點擊了按鈕之后我跳轉到了另外的Framgment,直接用父類的startToFragment()方法,操作起來還是很簡單的。

在第二個頁面我在這里進行了參數的傳遞和獲取。

AnotherFragment:

import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;

/**
 * Created by Bob on 2016/4/5.
 */
public class AnotherFragment extends BasePadFragment implements View.OnClickListener {

    private Button btnToThirdPage;
    private EditText mEdtName;
    private Spinner mSpinText;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.layout_another, null);
        mContext = getActivity();
        btnToThirdPage = (Button) view.findViewById(R.id.btn_another);
        mEdtName = (EditText)view.findViewById(R.id.edt_name);
        mSpinText = (Spinner)view.findViewById(R.id.spi_text);
        String [] textArray = getResources().getStringArray(R.array.text);
        ArrayAdapter<String> textAdapter = new ArrayAdapter<String>(mContext,R.layout.myspinner,textArray);
        textAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mSpinText.setAdapter(textAdapter);
        btnToThirdPage.setOnClickListener(this);
        return view;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_another:
                ThirdFragment thirdFragment = new ThirdFragment();
                String name = mEdtName.getText().toString();
                Bundle bundle = new Bundle();
                if(name != null){
                    bundle.putString("name",name);
                }
                bundle.putString("password","12345678");
                thirdFragment.setArguments(bundle);
                startToFragment(getActivity(), R.id.layout_container, thirdFragment);
                break;
            default:
                break;
        }
    }
}

  同樣在按鈕的點擊事件中,我利用Bundle進行數據的傳遞,使用起來也是挺簡單的。在第三個界面進行數據的獲取也挺簡單。

ThirdFragment:

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



/**
 * Created by Bob on 2016/4/11.
 */
public class ThirdFragment extends Fragment {
    private TextView tvName;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.layout_third_fragment, null);
        tvName = (TextView)view.findViewById(R.id.tv_name);
        Bundle bundle  = getArguments();
        String name =bundle.getString("name");
        String password = bundle.getString("password");
        if(null != name){
            tvName.setText(name+"    "+password);
        }
        return view;
    }
}

  簡單的思路,但是在引用到項目里面去的時候又發現了一個比較匪夷所思的問題,那就是盡管進行了fragment的跳轉,但是上一個Fragment好像並沒有被遮蓋,就是說在當前的fragment還能操作上一個fragment。這個就有點坑爹了,后面在找了好些資料之后終於把問題解決。下面是最終的BasePadFragment的StartToFragment方法。

/**
     * 跳轉到另外一個fragment的方法
     * @param  currentFragment 當前fragment
     * @param container:當前fragment所處的容器
     * @param newFragment 下一個fragment
     * */
    public void startToFragment(Fragment currentFragment,Context context,int container,Fragment newFragment){
        if(currentFragment != newFragment){
            manager = getFragmentManager();
            transaction = manager.beginTransaction();
            if(! newFragment.isAdded()){
                transaction.hide(currentFragment).add(container,newFragment);
                transaction.addToBackStack(context.getClass().getName());
                transaction.commit();
            }else{
               transaction.hide(currentFragment).show(newFragment);
                transaction.addToBackStack(context.getClass().getName());
                transaction.commit();
            }
        }
    }

  這樣就很好的處理了上一個Fragment不能被遮蓋的問題。處理的邏輯是這樣,先判斷新的fragment是否被add了進來如果沒有的話就hide掉上面的fragment,再把新的fragmentadd進來,如果add進來了就直接hide掉上一個fragment,直接壓棧並提交。

 源碼地址:https://github.com/bobLion/MultiScreenDemo


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM