Android 动态创建Fragment(可根据服务端下发的title动态创建)

35 篇文章 0 订阅

不废话先上代码应该都能看懂

1.创建fragment类

public class FragmentTest extends Fragment {

    TextView mTxtNumber;

    int mPosition;
    String mTitle = "";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = View.inflate(getActivity(), R.layout.fragment_tab, null);

        mPosition = getArguments().getInt("position");
        mTitle = getArguments().getString("title");
        mTxtNumber = (TextView) view.findViewById(R.id.txt_fragment_number);

        mTxtNumber.setText("第" + mPosition + "个fragment==" + mTitle);
        return view;
    }
}

布局fragment_tab.xml

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

    <TextView
        android:id="@+id/txt_fragment_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textColor="@color/color_333333"
        android:layout_margin="20dp"
        android:text="第几个fragment"/>

</LinearLayout>

2.添加TabLayout 这个是修改后的源码我就不解析了有时间自己看就行

/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


/**
 * To be used with ViewPager to provide a tab indicator component which give
 * constant feedback as to the user's scroll progress.
 * <p>
 * To use the component, simply add it to your view hierarchy. Then in your
 * {@link android.app.Activity} or {@link android.support.v4.app.Fragment} call
 * {@link #setViewPager(ViewPager)} providing it the ViewPager this layout is
 * being used for.
 * <p>
 * The colors can be customized in two ways. The first and simplest is to
 * provide an array of colors via {@link #setSelectedIndicatorColors(int...)}.
 * The alternative is via the {@link TabColorizer} interface which provides you
 * complete control over which color is used for any individual position.
 * <p>
 * The views used as tabs can be customized by calling
 * {@link #setCustomTabView(int, int)}, providing the layout ID of your custom
 * layout.
 */
public class SlidingTabLayout extends HorizontalScrollView {
	/**
	 * Allows complete control over the colors drawn in the tab layout. Set with
	 * {@link #setCustomTabColorizer(TabColorizer)}.
	 */
	public interface TabColorizer {

		/**
		 * @return return the color of the indicator used when {@code position}
		 *         is selected.
		 */
		int getIndicatorColor(int position);

	}

	private static final int TITLE_OFFSET_DIPS = 24;
	private static final int TAB_VIEW_PADDING_DIPS = 16;
	private static final int TAB_VIEW_TEXT_SIZE_SP = 12;

	private int mTitleOffset;

	private int mTabViewLayoutId;
	private int mTabViewTextViewId;
	private boolean mDistributeEvenly;

	private ViewPager mViewPager;
	private SparseArray<String> mContentDescriptions = new SparseArray<String>();
	private ViewPager.OnPageChangeListener mViewPagerPageChangeListener;

	private final SlidingTabStrip mTabStrip;

	public SlidingTabLayout(Context context) {
		this(context, null);
	}

	public SlidingTabLayout(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		// Disable the Scroll Bar
		setHorizontalScrollBarEnabled(false);
		// Make sure that the Tab Strips fills this View
		setFillViewport(true);

		mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources()
				.getDisplayMetrics().density);

		mTabStrip = new SlidingTabStrip(context);
		addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

	}

	/**
	 * Set the custom {@link TabColorizer} to be used.
	 * 
	 * If you only require simple custmisation then you can use
	 * {@link #setSelectedIndicatorColors(int...)} to achieve similar effects.
	 */
	public void setCustomTabColorizer(TabColorizer tabColorizer) {
		mTabStrip.setCustomTabColorizer(tabColorizer);
	}

	public void setDistributeEvenly(boolean distributeEvenly) {
		mDistributeEvenly = distributeEvenly;
	}

	/**
	 * Sets the colors to be used for indicating the selected tab. These colors
	 * are treated as a circular array. Providing one color will mean that all
	 * tabs are indicated with the same color.
	 */
	public void setSelectedIndicatorColors(int... colors) {
		mTabStrip.setSelectedIndicatorColors(colors);
	}

	/**
	 * Set the {@link ViewPager.OnPageChangeListener}. When using
	 * {@link SlidingTabLayout} you are required to set any
	 * {@link ViewPager.OnPageChangeListener} through this method. This is so
	 * that the layout can update it's scroll position correctly.
	 * 
	 * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener)
	 */
	public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
		mViewPagerPageChangeListener = listener;
	}

	/**
	 * Set the custom layout to be inflated for the tab views.
	 * 
	 * @param layoutResId
	 *            Layout id to be inflated
	 * @param textViewId
	 *            id of the {@link TextView} in the inflated view
	 */
	public void setCustomTabView(int layoutResId, int textViewId) {
		mTabViewLayoutId = layoutResId;
		mTabViewTextViewId = textViewId;
	}

	/**
	 * Sets the associated view pager. Note that the assumption here is that the
	 * pager content (number of tabs and tab titles) does not change after this
	 * call has been made.
	 */
	public void setViewPager(ViewPager viewPager) {
		mTabStrip.removeAllViews();

		mViewPager = viewPager;
		if (viewPager != null) {
			viewPager.addOnPageChangeListener(new InternalViewPagerListener());
			populateTabStrip();
		}
	}

	/**
	 * Create a default view to be used for tabs. This is called if a custom tab
	 * view is not set via {@link #setCustomTabView(int, int)}.
	 */
	@SuppressLint("NewApi")
	protected TextView createDefaultTabView(Context context) {
		TextView textView = new TextView(context);
		textView.setGravity(Gravity.CENTER);
		textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP);
		textView.setTypeface(Typeface.DEFAULT_BOLD);
		textView.setLayoutParams(new LinearLayout.LayoutParams(
				ViewGroup.LayoutParams.WRAP_CONTENT,
				ViewGroup.LayoutParams.WRAP_CONTENT));

		TypedValue outValue = new TypedValue();
		getContext().getTheme().resolveAttribute(
				android.R.attr.selectableItemBackground, outValue, true);
		textView.setBackgroundResource(outValue.resourceId);
		textView.setAllCaps(true);

		int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources()
				.getDisplayMetrics().density);
		textView.setPadding(padding, padding, padding, padding);

		return textView;
	}

	private void populateTabStrip() {
		final PagerAdapter adapter = mViewPager.getAdapter();
		final OnClickListener tabClickListener = new TabClickListener();

		for (int i = 0; i < adapter.getCount(); i++) {
			View tabView = null;
			TextView tabTitleView = null;

			if (mTabViewLayoutId != 0) {
				// If there is a custom tab view layout id set, try and inflate
				// it
				tabView = LayoutInflater.from(getContext()).inflate(
						mTabViewLayoutId, mTabStrip, false);
				tabTitleView = (TextView) tabView
						.findViewById(mTabViewTextViewId);

			}

			if (tabView == null) {
				tabView = createDefaultTabView(getContext());
			}

			if (tabTitleView == null && TextView.class.isInstance(tabView)) {
				tabTitleView = (TextView) tabView;
			}

			if (mDistributeEvenly) {
				LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView
						.getLayoutParams();
				lp.width = 0;
				lp.weight = 1;
			}

			tabTitleView.setText(adapter.getPageTitle(i));

			tabView.setOnClickListener(tabClickListener);
			String desc = mContentDescriptions.get(i, null);
			if (desc != null) {
				tabView.setContentDescription(desc);
			}

			mTabStrip.addView(tabView);
			if (i == mViewPager.getCurrentItem()) {
				tabView.setSelected(true);
			}
		}
	}

	public void setContentDescription(int i, String desc) {
		mContentDescriptions.put(i, desc);
	}

	@Override
	protected void onAttachedToWindow() {
		super.onAttachedToWindow();

		if (mViewPager != null) {
			scrollToTab(mViewPager.getCurrentItem(), 0);
		}
	}

	private void scrollToTab(int tabIndex, int positionOffset) {
		final int tabStripChildCount = mTabStrip.getChildCount();
		if (tabStripChildCount == 0 || tabIndex < 0
				|| tabIndex >= tabStripChildCount) {
			return;
		}

		View selectedChild = mTabStrip.getChildAt(tabIndex);
		if (selectedChild != null) {
			int targetScrollX = selectedChild.getLeft() + positionOffset;

//			if (tabIndex > 0 || positionOffset > 0) {
				// If we're not at the first child and are mid-scroll, make sure
				// we obey the offset
				targetScrollX -= mTitleOffset; //item向左偏移用margin以扩大linearlayout的范围以适应mTitleOffset
//			}

			scrollTo(targetScrollX, 0);
		}
	}

	private class InternalViewPagerListener implements
			ViewPager.OnPageChangeListener {
		private int mScrollState;

		@Override
		public void onPageScrolled(int position, float positionOffset,
				int positionOffsetPixels) {
			int tabStripChildCount = mTabStrip.getChildCount();
			if ((tabStripChildCount == 0) || (position < 0)
					|| (position >= tabStripChildCount)) {
				return;
			}

			mTabStrip.onViewPagerPageChanged(position, positionOffset);

			View selectedTitle = mTabStrip.getChildAt(position);
			int extraOffset = (selectedTitle != null) ? (int) (positionOffset * selectedTitle
					.getWidth()) : 0;
			scrollToTab(position, extraOffset);

			if (mViewPagerPageChangeListener != null) {
				mViewPagerPageChangeListener.onPageScrolled(position,
						positionOffset, positionOffsetPixels);
			}
		}

		@Override
		public void onPageScrollStateChanged(int state) {
			mScrollState = state;

			if (mViewPagerPageChangeListener != null) {
				mViewPagerPageChangeListener.onPageScrollStateChanged(state);
			}
		}

		@Override
		public void onPageSelected(int position) {
			if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
				mTabStrip.onViewPagerPageChanged(position, 0f);
				scrollToTab(position, 0);
			}
			for (int i = 0; i < mTabStrip.getChildCount(); i++) {
				mTabStrip.getChildAt(i).setSelected(position == i);
			}
			if (mViewPagerPageChangeListener != null) {
				mViewPagerPageChangeListener.onPageSelected(position);
			}
		}

	}

	private class TabClickListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			for (int i = 0; i < mTabStrip.getChildCount(); i++) {
				if (v == mTabStrip.getChildAt(i)) {
					mViewPager.setCurrentItem(i);
					return;
				}
			}
		}
	}

}

/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


class SlidingTabStrip extends LinearLayout {

	private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 0;
	private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26;
	private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 3;
	private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5;

	private final int mBottomBorderThickness;
	private final Paint mBottomBorderPaint;

	private final int mSelectedIndicatorThickness;
	private final Paint mSelectedIndicatorPaint;

	private final int mDefaultBottomBorderColor;

	private int mSelectedPosition;
	private float mSelectionOffset;

	private SlidingTabLayout.TabColorizer mCustomTabColorizer;
	private final SimpleTabColorizer mDefaultTabColorizer;

	SlidingTabStrip(Context context) {
		this(context, null);
	}

	SlidingTabStrip(Context context, AttributeSet attrs) {
		super(context, attrs);
		setWillNotDraw(false);

		final float density = getResources().getDisplayMetrics().density;

		TypedValue outValue = new TypedValue();
		context.getTheme().resolveAttribute(android.R.attr.colorForeground, outValue,
				true);
		final int themeForegroundColor = outValue.data;

		mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor,
				DEFAULT_BOTTOM_BORDER_COLOR_ALPHA);

		mDefaultTabColorizer = new SimpleTabColorizer();
		mDefaultTabColorizer
				.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR);

		mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density);
		mBottomBorderPaint = new Paint();
		mBottomBorderPaint.setColor(mDefaultBottomBorderColor);

		mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density);
		mSelectedIndicatorPaint = new Paint();
	}

	void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) {
		mCustomTabColorizer = customTabColorizer;
		invalidate();
	}

	void setSelectedIndicatorColors(int... colors) {
		// Make sure that the custom colorizer is removed
		mCustomTabColorizer = null;
		mDefaultTabColorizer.setIndicatorColors(colors);

		invalidate();
	}

	void onViewPagerPageChanged(int position, float positionOffset) {
		mSelectedPosition = position;
		mSelectionOffset = positionOffset;
		invalidate();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		final int height = getHeight();
		final int childCount = getChildCount();
		final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null ? mCustomTabColorizer
				: mDefaultTabColorizer;

		// Thick colored underline below the current selection
		if (childCount > 0) {
			View selectedTitle = getChildAt(mSelectedPosition);
			int left = selectedTitle.getLeft();
			int right = selectedTitle.getRight();
			int color = tabColorizer.getIndicatorColor(mSelectedPosition);

			if (mSelectionOffset > 0f
					&& mSelectedPosition < (getChildCount() - 1)) {
				int nextColor = tabColorizer
						.getIndicatorColor(mSelectedPosition + 1);
				if (color != nextColor) {
					color = blendColors(nextColor, color, mSelectionOffset);
				}

				// Draw the selection partway between the tabs
				View nextTitle = getChildAt(mSelectedPosition + 1);
				left = (int) (mSelectionOffset * nextTitle.getLeft() + (1.0f - mSelectionOffset)
						* left);
				right = (int) (mSelectionOffset * nextTitle.getRight() + (1.0f - mSelectionOffset)
						* right);
			}

			mSelectedIndicatorPaint.setColor(color);

			canvas.drawRect(left, height - mSelectedIndicatorThickness, right,
					height, mSelectedIndicatorPaint);
		}

		// Thin underline along the entire bottom edge
		canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height,
				mBottomBorderPaint);
	}

	/**
	 * Set the alpha value of the {@code color} to be the given {@code alpha}
	 * value.
	 */
	private static int setColorAlpha(int color, byte alpha) {
		return Color.argb(alpha, Color.red(color), Color.green(color),
				Color.blue(color));
	}

	/**
	 * Blend {@code color1} and {@code color2} using the given ratio.
	 * 
	 * @param ratio
	 *            of which to blend. 1.0 will return {@code color1}, 0.5 will
	 *            give an even blend, 0.0 will return {@code color2}.
	 */
	private static int blendColors(int color1, int color2, float ratio) {
		final float inverseRation = 1f - ratio;
		float r = (Color.red(color1) * ratio)
				+ (Color.red(color2) * inverseRation);
		float g = (Color.green(color1) * ratio)
				+ (Color.green(color2) * inverseRation);
		float b = (Color.blue(color1) * ratio)
				+ (Color.blue(color2) * inverseRation);
		return Color.rgb((int) r, (int) g, (int) b);
	}

	private static class SimpleTabColorizer implements
			SlidingTabLayout.TabColorizer {
		private int[] mIndicatorColors;

		@Override
		public final int getIndicatorColor(int position) {
			return mIndicatorColors[position % mIndicatorColors.length];
		}

		void setIndicatorColors(int... colors) {
			mIndicatorColors = colors;
		}
	}
}

然后就是MainActivity

/**
 * 实现动态添加Fragment,头部可动态添加,fragment可动态添加,非常的灵活,
 * 同时加了线条滑动效果
 */
public class MainActivity extends AppCompatActivity {

    SlidingTabLayout mTab;

    ViewPager mViewPager;
    FragmentPagerAdapter mAdapter;

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

        initView();
    }

    private void initView(){
        mTab = (SlidingTabLayout) findViewById(R.id.tab_fragment);
        mViewPager = (ViewPager) findViewById(R.id.viewpager_fragment);

        mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
            // titles作为滑动标题栏,动态添加数据进去就可以了
            String[] titles = { "全部", "待付款", "待发货" };

            @Override
            public Fragment getItem(int position) { // 开始动态添加fragment
                FragmentTest fragment = new FragmentTest();
                Bundle bundle = new Bundle();
                bundle.putInt("position", position);
                bundle.putString("title", titles[position]);
                fragment.setArguments(bundle);
                return fragment;
            }

            @Override
            public int getCount() { // 添加fragment个数
                return titles.length;
            }

            @Override
            public CharSequence getPageTitle(int position) { // 添加fragment标题
                return titles[position];
            }
        };
        mViewPager.setAdapter(mAdapter);

        mTab.setCustomTabView(R.layout.custom_tab, 0); // 添加头部xml,可自定义
        mTab.setSelectedIndicatorColors(0xffe8303d); // 下滑线的颜色
        mTab.setBackgroundColor(0xffffffff); // 头部背景颜色
        mTab.setViewPager(mViewPager);
    }
}

布局activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.wd.fragments.utils.SlidingTabLayout
        android:id="@+id/tab_fragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="@color/color_DEDEDE" />

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewpager_fragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >
    </androidx.viewpager.widget.ViewPager>

</LinearLayout>

用于添加头布局custom_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="0dp"
    android:layout_weight="1"
    android:lines="1"
    android:layout_height="40dp"
    android:textSize="14sp"
    android:textColor="@color/color_333333"
    android:gravity="center"/>

<!--
头部的布局可自定义
1.等比宽度,我这里是使用了权重layout_weight,头部数据少的情况下可使用
2.使用固定宽度,layout_width,这样可以避免在添加过多头部数据时显示不全的问题,
 -->

效果图片在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王鑫林呀!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值