Commit 96ab3599eec2b0d469d3bdd9efd28d97368391b5
1 parent
4a974f52
添加首页标签
Showing
28 changed files
with
775 additions
and
20 deletions
app/build.gradle
| @@ -11,6 +11,9 @@ android { | @@ -11,6 +11,9 @@ android { | ||
| 11 | versionName "1.0" | 11 | versionName "1.0" |
| 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" |
| 13 | } | 13 | } |
| 14 | + dataBinding { | ||
| 15 | + enabled true | ||
| 16 | + } | ||
| 14 | buildTypes { | 17 | buildTypes { |
| 15 | release { | 18 | release { |
| 16 | minifyEnabled false | 19 | minifyEnabled false |
app/src/main/AndroidManifest.xml
| @@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
| 9 | android:roundIcon="@mipmap/ic_launcher_round" | 9 | android:roundIcon="@mipmap/ic_launcher_round" |
| 10 | android:supportsRtl="true" | 10 | android:supportsRtl="true" |
| 11 | android:theme="@style/AppTheme"> | 11 | android:theme="@style/AppTheme"> |
| 12 | - <activity android:name=".MainActivity"> | 12 | + <activity android:name=".main.ui.activity.MainActivity"> |
| 13 | <intent-filter> | 13 | <intent-filter> |
| 14 | <action android:name="android.intent.action.MAIN" /> | 14 | <action android:name="android.intent.action.MAIN" /> |
| 15 | 15 |
app/src/main/java/com/cnlive/gundam/MainActivity.java deleted
100644 → 0
| 1 | -package com.cnlive.gundam; | ||
| 2 | - | ||
| 3 | -import android.support.v7.app.AppCompatActivity; | ||
| 4 | -import android.os.Bundle; | ||
| 5 | - | ||
| 6 | -public class MainActivity extends AppCompatActivity { | ||
| 7 | - | ||
| 8 | - @Override | ||
| 9 | - protected void onCreate(Bundle savedInstanceState) { | ||
| 10 | - super.onCreate(savedInstanceState); | ||
| 11 | - setContentView(R.layout.activity_main); | ||
| 12 | - } | ||
| 13 | -} |
app/src/main/java/com/cnlive/gundam/main/ui/activity/MainActivity.java
0 → 100644
| 1 | +package com.cnlive.gundam.main.ui.activity; | ||
| 2 | + | ||
| 3 | +import android.databinding.DataBindingUtil; | ||
| 4 | +import android.os.Bundle; | ||
| 5 | +import android.support.v7.app.AppCompatActivity; | ||
| 6 | + | ||
| 7 | +import com.cnlive.gundam.R; | ||
| 8 | +import com.cnlive.gundam.databinding.ActivityMainBinding; | ||
| 9 | +import com.cnlive.gundam.main.ui.fragment.ConfigFragment; | ||
| 10 | +import com.cnlive.gundam.main.ui.fragment.HomeFragment; | ||
| 11 | +import com.cnlive.gundam.main.ui.fragment.LiveFragment; | ||
| 12 | +import com.cnlive.gundam.main.ui.fragment.UGCListFragment; | ||
| 13 | +import com.cnlive.gundam.main.ui.widget.FragmentTabHost; | ||
| 14 | + | ||
| 15 | +import java.util.Arrays; | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * Created by xiansong on 2017/6/27. | ||
| 19 | + */ | ||
| 20 | + | ||
| 21 | +public class MainActivity extends AppCompatActivity implements FragmentTabHost.OnSetCurrentTabListener { | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + protected void onCreate(Bundle savedInstanceState) { | ||
| 25 | + super.onCreate(savedInstanceState); | ||
| 26 | + ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); | ||
| 27 | + binding.setContentId(R.id.realtabcontent); | ||
| 28 | + binding.setOnSetCurrentTabListener(this); | ||
| 29 | + binding.setTabItemInfoList(Arrays.asList( | ||
| 30 | + FragmentTabHost.newTab("home", R.layout.indicator_main_home, HomeFragment.class), | ||
| 31 | + FragmentTabHost.newTab("media", R.layout.indicator_main_live_tv, UGCListFragment.class), | ||
| 32 | + FragmentTabHost.newTab("stream", R.layout.indicator_main_stream, null), | ||
| 33 | + FragmentTabHost.newTab("live", R.layout.indicator_main_live, LiveFragment.class), | ||
| 34 | + FragmentTabHost.newTab("config", R.layout.indicator_main_mine, ConfigFragment.class) | ||
| 35 | + )); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @Override | ||
| 39 | + public boolean onSetCurrentTab(String tag) { | ||
| 40 | + switch (tag) { | ||
| 41 | + case "stream": | ||
| 42 | + //TODO 启动直播推流页面0 | ||
| 43 | + return true; | ||
| 44 | + } | ||
| 45 | + return false; | ||
| 46 | + } | ||
| 47 | +} | ||
| 0 | \ No newline at end of file | 48 | \ No newline at end of file |
app/src/main/java/com/cnlive/gundam/main/ui/fragment/ConfigFragment.java
0 → 100644
app/src/main/java/com/cnlive/gundam/main/ui/fragment/HomeFragment.java
0 → 100644
app/src/main/java/com/cnlive/gundam/main/ui/fragment/LiveFragment.java
0 → 100644
app/src/main/java/com/cnlive/gundam/main/ui/fragment/UGCListFragment.java
0 → 100644
app/src/main/java/com/cnlive/gundam/main/ui/widget/FragmentTabHost.java
0 → 100644
| 1 | +package com.cnlive.gundam.main.ui.widget; | ||
| 2 | + | ||
| 3 | +import android.content.Context; | ||
| 4 | +import android.content.res.TypedArray; | ||
| 5 | +import android.graphics.drawable.Drawable; | ||
| 6 | +import android.os.Bundle; | ||
| 7 | +import android.os.Parcel; | ||
| 8 | +import android.os.Parcelable; | ||
| 9 | +import android.support.annotation.NonNull; | ||
| 10 | +import android.support.annotation.Nullable; | ||
| 11 | +import android.support.v4.app.Fragment; | ||
| 12 | +import android.support.v4.app.FragmentActivity; | ||
| 13 | +import android.support.v4.app.FragmentManager; | ||
| 14 | +import android.support.v4.app.FragmentTransaction; | ||
| 15 | +import android.util.AttributeSet; | ||
| 16 | +import android.view.LayoutInflater; | ||
| 17 | +import android.view.View; | ||
| 18 | +import android.view.ViewGroup; | ||
| 19 | +import android.widget.FrameLayout; | ||
| 20 | +import android.widget.LinearLayout; | ||
| 21 | +import android.widget.TabHost; | ||
| 22 | +import android.widget.TabWidget; | ||
| 23 | + | ||
| 24 | +import com.cnlive.gundam.R; | ||
| 25 | + | ||
| 26 | +import java.util.ArrayList; | ||
| 27 | +import java.util.List; | ||
| 28 | + | ||
| 29 | +public class FragmentTabHost extends TabHost | ||
| 30 | + implements TabHost.OnTabChangeListener { | ||
| 31 | + private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); | ||
| 32 | + private FrameLayout mRealTabContent; | ||
| 33 | + private Context mContext; | ||
| 34 | + private FragmentManager mFragmentManager; | ||
| 35 | + private int mContainerId; | ||
| 36 | + private OnSetCurrentTabListener onSetCurrentTabListener; | ||
| 37 | + private TabHost.OnTabChangeListener mOnTabChangeListener; | ||
| 38 | + private TabInfo mLastTab; | ||
| 39 | + private boolean mAttached; | ||
| 40 | + private Drawable mDiciderDrawable; | ||
| 41 | + | ||
| 42 | + private List<TabSpec> mTabSpecs = new ArrayList<TabSpec>(2); | ||
| 43 | + | ||
| 44 | + public interface OnSetCurrentTabListener { | ||
| 45 | + boolean onSetCurrentTab(String tag); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + public static final class TabItemInfo{ | ||
| 49 | + private final String tag; | ||
| 50 | + private final int layoutId; | ||
| 51 | + private final Class<?> clss; | ||
| 52 | + | ||
| 53 | + public TabItemInfo(String tag, int layoutId, Class<?> clss) { | ||
| 54 | + this.tag = tag; | ||
| 55 | + this.layoutId = layoutId; | ||
| 56 | + this.clss = clss; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + static final class TabInfo { | ||
| 63 | + private final String tag; | ||
| 64 | + private final Class<?> clss; | ||
| 65 | + private final Bundle args; | ||
| 66 | + private Fragment fragment; | ||
| 67 | + | ||
| 68 | + TabInfo(String _tag, Class<?> _class, Bundle _args) { | ||
| 69 | + tag = _tag; | ||
| 70 | + clss = _class; | ||
| 71 | + args = _args; | ||
| 72 | + } | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + static class DummyTabFactory implements TabHost.TabContentFactory { | ||
| 76 | + private final Context mContext; | ||
| 77 | + | ||
| 78 | + public DummyTabFactory(Context context) { | ||
| 79 | + mContext = context; | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + @Override | ||
| 83 | + public View createTabContent(String tag) { | ||
| 84 | + View v = new View(mContext); | ||
| 85 | + v.setMinimumWidth(0); | ||
| 86 | + v.setMinimumHeight(0); | ||
| 87 | + return v; | ||
| 88 | + } | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + static class SavedState extends BaseSavedState { | ||
| 92 | + String curTab; | ||
| 93 | + | ||
| 94 | + SavedState(Parcelable superState) { | ||
| 95 | + super(superState); | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + private SavedState(Parcel in) { | ||
| 99 | + super(in); | ||
| 100 | + curTab = in.readString(); | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + @Override | ||
| 104 | + public void writeToParcel(Parcel out, int flags) { | ||
| 105 | + super.writeToParcel(out, flags); | ||
| 106 | + out.writeString(curTab); | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + @Override | ||
| 110 | + public String toString() { | ||
| 111 | + return "FragmentTabHost.SavedState{" | ||
| 112 | + + Integer.toHexString(System.identityHashCode(this)) | ||
| 113 | + + " curTab=" + curTab + "}"; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + public static final Parcelable.Creator<SavedState> CREATOR | ||
| 117 | + = new Parcelable.Creator<SavedState>() { | ||
| 118 | + public SavedState createFromParcel(Parcel in) { | ||
| 119 | + return new SavedState(in); | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + public SavedState[] newArray(int size) { | ||
| 123 | + return new SavedState[size]; | ||
| 124 | + } | ||
| 125 | + }; | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + public static TabItemInfo newTab(String tag, int layoutId, Class<?> clss) { | ||
| 129 | + return new FragmentTabHost.TabItemInfo(tag, layoutId, clss); | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + public FragmentTabHost(Context context) { | ||
| 133 | + // Note that we call through to the version that takes an AttributeSet, | ||
| 134 | + // because the simple Context construct can result in a broken object! | ||
| 135 | + this(context, null); | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + public FragmentTabHost(Context context, AttributeSet attrs) { | ||
| 139 | + super(context, attrs); | ||
| 140 | + initFragmentTabHost(context, attrs); | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + private void initFragmentTabHost(Context context, AttributeSet attrs) { | ||
| 144 | + TypedArray a; | ||
| 145 | + a = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.inflatedId}, 0, 0); | ||
| 146 | + try { | ||
| 147 | + mContainerId = a.getResourceId(0, 0); | ||
| 148 | + }finally { | ||
| 149 | + a.recycle(); | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + a = context.obtainStyledAttributes(attrs, R.styleable.FragmentTabHost); | ||
| 153 | + try { | ||
| 154 | + mDiciderDrawable = a.getDrawable(R.styleable.FragmentTabHost_dividerDrawable); | ||
| 155 | + }finally { | ||
| 156 | + a.recycle(); | ||
| 157 | + } | ||
| 158 | + super.setOnTabChangedListener(this); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + private void ensureHierarchy(Context context) { | ||
| 162 | + // If owner hasn't made its own view hierarchy, then as a convenience | ||
| 163 | + // we will construct a standard one here. | ||
| 164 | + if (findViewById(android.R.id.tabs) == null) { | ||
| 165 | + LinearLayout ll = new LinearLayout(context); | ||
| 166 | + ll.setOrientation(LinearLayout.VERTICAL); | ||
| 167 | + addView(ll, new FrameLayout.LayoutParams( | ||
| 168 | + ViewGroup.LayoutParams.FILL_PARENT, | ||
| 169 | + ViewGroup.LayoutParams.FILL_PARENT)); | ||
| 170 | + | ||
| 171 | + TabWidget tw = new TabWidget(context); | ||
| 172 | + tw.setId(android.R.id.tabs); | ||
| 173 | + tw.setOrientation(TabWidget.HORIZONTAL); | ||
| 174 | + ll.addView(tw, new LinearLayout.LayoutParams( | ||
| 175 | + ViewGroup.LayoutParams.FILL_PARENT, | ||
| 176 | + ViewGroup.LayoutParams.WRAP_CONTENT, 0)); | ||
| 177 | + | ||
| 178 | + FrameLayout fl = new FrameLayout(context); | ||
| 179 | + fl.setId(android.R.id.tabcontent); | ||
| 180 | + ll.addView(fl, new LinearLayout.LayoutParams(0, 0, 0)); | ||
| 181 | + | ||
| 182 | + mRealTabContent = fl = new FrameLayout(context); | ||
| 183 | + mRealTabContent.setId(mContainerId); | ||
| 184 | + ll.addView(fl, new LinearLayout.LayoutParams( | ||
| 185 | + LinearLayout.LayoutParams.FILL_PARENT, 0, 1)); | ||
| 186 | + } | ||
| 187 | + } | ||
| 188 | + | ||
| 189 | + /** | ||
| 190 | + * @deprecated Don't call the original TabHost setup, you must instead | ||
| 191 | + * call {@link #setup(Context, FragmentManager)} or | ||
| 192 | + * {@link #setup(Context, FragmentManager, int)}. | ||
| 193 | + */ | ||
| 194 | + @Override | ||
| 195 | + @Deprecated | ||
| 196 | + public void setup() { | ||
| 197 | + throw new IllegalStateException( | ||
| 198 | + "Must call setup() that takes a Context and FragmentManager"); | ||
| 199 | + } | ||
| 200 | + | ||
| 201 | + public void setup(Context context, FragmentManager manager) { | ||
| 202 | + ensureHierarchy(context); // Ensure views required by super.setup() | ||
| 203 | + super.setup(); | ||
| 204 | + mContext = context; | ||
| 205 | + mFragmentManager = manager; | ||
| 206 | + ensureContent(); | ||
| 207 | + setDividerDrawable(mDiciderDrawable); | ||
| 208 | + } | ||
| 209 | + | ||
| 210 | + public void setup(Context context, FragmentManager manager, int containerId) { | ||
| 211 | + ensureHierarchy(context); // Ensure views required by super.setup() | ||
| 212 | + super.setup(); | ||
| 213 | + mContext = context; | ||
| 214 | + mFragmentManager = manager; | ||
| 215 | + mContainerId = containerId; | ||
| 216 | + ensureContent(); | ||
| 217 | + setDividerDrawable(mDiciderDrawable); | ||
| 218 | + mRealTabContent.setId(containerId); | ||
| 219 | + | ||
| 220 | + // We must have an ID to be able to save/restore our state. If | ||
| 221 | + // the owner hasn't set one at this point, we will set it ourself. | ||
| 222 | + if (getId() == View.NO_ID) { | ||
| 223 | + setId(android.R.id.tabhost); | ||
| 224 | + } | ||
| 225 | + } | ||
| 226 | + | ||
| 227 | + /** | ||
| 228 | + * 设置内容ID并初始化 | ||
| 229 | + * @param contentId 展示内容的Layout ID | ||
| 230 | + */ | ||
| 231 | + public void setContentId(int contentId){ | ||
| 232 | + FragmentActivity activity = ((FragmentActivity)getContext()); | ||
| 233 | + setup(activity, activity.getSupportFragmentManager(), contentId); | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + /** | ||
| 237 | + * 添加标签内容信息 | ||
| 238 | + * @param list | ||
| 239 | + */ | ||
| 240 | + public void setTabItemList(List<TabItemInfo> list) { | ||
| 241 | + for (TabItemInfo item : list) addTab(item.tag, item.layoutId, item.clss, null); | ||
| 242 | + } | ||
| 243 | + | ||
| 244 | + private void ensureContent() { | ||
| 245 | + if (mRealTabContent == null) { | ||
| 246 | + mRealTabContent = (FrameLayout) findViewById(mContainerId); | ||
| 247 | + if (mRealTabContent == null) { | ||
| 248 | + throw new IllegalStateException( | ||
| 249 | + "No tab content FrameLayout found for id " + mContainerId); | ||
| 250 | + } | ||
| 251 | + } | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + @Override | ||
| 255 | + public void setOnTabChangedListener(OnTabChangeListener l) { | ||
| 256 | + mOnTabChangeListener = l; | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) { | ||
| 260 | + tabSpec.setContent(new DummyTabFactory(mContext)); | ||
| 261 | + String tag = tabSpec.getTag(); | ||
| 262 | + | ||
| 263 | + TabInfo info = new TabInfo(tag, clss, args); | ||
| 264 | + | ||
| 265 | + if (mAttached) { | ||
| 266 | + // If we are already attached to the window, then check to make | ||
| 267 | + // sure this tab's fragment is inactive if it exists. This shouldn't | ||
| 268 | + // normally happen. | ||
| 269 | + info.fragment = mFragmentManager.findFragmentByTag(tag); | ||
| 270 | + if (info.fragment != null && !info.fragment.isDetached()) { | ||
| 271 | + FragmentTransaction ft = mFragmentManager.beginTransaction(); | ||
| 272 | + ft.detach(info.fragment); | ||
| 273 | + ft.commitAllowingStateLoss(); | ||
| 274 | + } | ||
| 275 | + } | ||
| 276 | + | ||
| 277 | + mTabs.add(info); | ||
| 278 | + addTab(tabSpec); | ||
| 279 | + } | ||
| 280 | + | ||
| 281 | + public void addTab(String tag, int indicator, Class<?> clss, Bundle args) { | ||
| 282 | + View indicatorView = LayoutInflater.from(getContext()).inflate(indicator, null, false); | ||
| 283 | + TabSpec tabSpec = newTabSpec(tag).setIndicator(indicatorView); | ||
| 284 | + addTab(tabSpec, clss, args); | ||
| 285 | + } | ||
| 286 | + | ||
| 287 | + @Override | ||
| 288 | + protected void onAttachedToWindow() { | ||
| 289 | + super.onAttachedToWindow(); | ||
| 290 | + | ||
| 291 | + String currentTab = getCurrentTabTag(); | ||
| 292 | + | ||
| 293 | + // Go through all tabs and make sure their fragments match | ||
| 294 | + // the correct state. | ||
| 295 | + FragmentTransaction ft = null; | ||
| 296 | + for (int i = 0; i < mTabs.size(); i++) { | ||
| 297 | + TabInfo tab = mTabs.get(i); | ||
| 298 | + tab.fragment = mFragmentManager.findFragmentByTag(tab.tag); | ||
| 299 | + if (tab.fragment != null && !tab.fragment.isDetached()) { | ||
| 300 | + if (tab.tag.equals(currentTab)) { | ||
| 301 | + // The fragment for this tab is already there and | ||
| 302 | + // active, and it is what we really want to have | ||
| 303 | + // as the current tab. Nothing to do. | ||
| 304 | + mLastTab = tab; | ||
| 305 | + } else { | ||
| 306 | + // This fragment was restored in the active state, | ||
| 307 | + // but is not the current tab. Deactivate it. | ||
| 308 | + if (ft == null) { | ||
| 309 | + ft = mFragmentManager.beginTransaction(); | ||
| 310 | + } | ||
| 311 | + ft.detach(tab.fragment); | ||
| 312 | + } | ||
| 313 | + } | ||
| 314 | + } | ||
| 315 | + | ||
| 316 | + // We are now ready to go. Make sure we are switched to the | ||
| 317 | + // correct tab. | ||
| 318 | + mAttached = true; | ||
| 319 | + ft = doTabChanged(currentTab, ft); | ||
| 320 | + if (ft != null) { | ||
| 321 | + ft.commitAllowingStateLoss(); | ||
| 322 | + mFragmentManager.executePendingTransactions(); | ||
| 323 | + } | ||
| 324 | + } | ||
| 325 | + | ||
| 326 | + @Override | ||
| 327 | + protected void onDetachedFromWindow() { | ||
| 328 | + super.onDetachedFromWindow(); | ||
| 329 | + mAttached = false; | ||
| 330 | + } | ||
| 331 | + | ||
| 332 | + @Override | ||
| 333 | + protected Parcelable onSaveInstanceState() { | ||
| 334 | + Parcelable superState = super.onSaveInstanceState(); | ||
| 335 | + SavedState ss = new SavedState(superState); | ||
| 336 | + ss.curTab = getCurrentTabTag(); | ||
| 337 | + return ss; | ||
| 338 | + } | ||
| 339 | + | ||
| 340 | + @Override | ||
| 341 | + protected void onRestoreInstanceState(Parcelable state) { | ||
| 342 | + if (!(state instanceof SavedState)) { | ||
| 343 | + super.onRestoreInstanceState(state); | ||
| 344 | + return; | ||
| 345 | + } | ||
| 346 | + SavedState ss = (SavedState) state; | ||
| 347 | + super.onRestoreInstanceState(ss.getSuperState()); | ||
| 348 | + setCurrentTabByTag(ss.curTab); | ||
| 349 | + } | ||
| 350 | + | ||
| 351 | + @Override | ||
| 352 | + public void addTab(TabSpec tabSpec) { | ||
| 353 | + super.addTab(tabSpec); | ||
| 354 | + mTabSpecs.add(tabSpec); | ||
| 355 | + } | ||
| 356 | + | ||
| 357 | + @Override | ||
| 358 | + public void clearAllTabs() { | ||
| 359 | + super.clearAllTabs(); | ||
| 360 | + mTabSpecs.clear(); | ||
| 361 | + } | ||
| 362 | + | ||
| 363 | + @Override | ||
| 364 | + public void setCurrentTab(int index) { | ||
| 365 | + if (index < 0 || index >= mTabSpecs.size()) { | ||
| 366 | + return; | ||
| 367 | + } | ||
| 368 | + | ||
| 369 | + if (index == getCurrentTab()) { | ||
| 370 | + return; | ||
| 371 | + } | ||
| 372 | + if (onSetCurrentTabListener != null && onSetCurrentTabListener.onSetCurrentTab(mTabSpecs.get(index).getTag())) | ||
| 373 | + return; | ||
| 374 | + super.setCurrentTab(index); | ||
| 375 | + } | ||
| 376 | + | ||
| 377 | + @Override | ||
| 378 | + public void onTabChanged(String tabId) { | ||
| 379 | + if (mAttached) { | ||
| 380 | + FragmentTransaction ft = doTabChanged(tabId, null); | ||
| 381 | + if (ft != null) { | ||
| 382 | + ft.commitAllowingStateLoss(); | ||
| 383 | + } | ||
| 384 | + } | ||
| 385 | + if (mOnTabChangeListener != null) { | ||
| 386 | + mOnTabChangeListener.onTabChanged(tabId); | ||
| 387 | + } | ||
| 388 | + } | ||
| 389 | + | ||
| 390 | + public void setOnSetCurrentTabListener(@NonNull final FragmentTabHost.OnSetCurrentTabListener onSetCurrentTabListener) { | ||
| 391 | + this.onSetCurrentTabListener = onSetCurrentTabListener; | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + public void setDividerDrawable(@Nullable Drawable drawable){ | ||
| 395 | + getTabWidget().setDividerDrawable(drawable); | ||
| 396 | + } | ||
| 397 | + | ||
| 398 | + private FragmentTransaction doTabChanged(String tabId, FragmentTransaction ft) { | ||
| 399 | + TabInfo newTab = null; | ||
| 400 | + for (int i = 0; i < mTabs.size(); i++) { | ||
| 401 | + TabInfo tab = mTabs.get(i); | ||
| 402 | + if (tab.tag.equals(tabId)) { | ||
| 403 | + newTab = tab; | ||
| 404 | + } | ||
| 405 | + } | ||
| 406 | + if (newTab == null) { | ||
| 407 | + throw new IllegalStateException("No tab known for tag " + tabId); | ||
| 408 | + } | ||
| 409 | + if (mLastTab != newTab) { | ||
| 410 | + if (ft == null) { | ||
| 411 | + ft = mFragmentManager.beginTransaction(); | ||
| 412 | + } | ||
| 413 | + if (mLastTab != null) { | ||
| 414 | + if (mLastTab.fragment != null) { | ||
| 415 | + ft.detach(mLastTab.fragment); | ||
| 416 | + } | ||
| 417 | + } | ||
| 418 | + if (newTab != null) { | ||
| 419 | + if (newTab.fragment == null) { | ||
| 420 | + newTab.fragment = Fragment.instantiate(mContext, | ||
| 421 | + newTab.clss.getName(), newTab.args); | ||
| 422 | + ft.add(mContainerId, newTab.fragment, newTab.tag); | ||
| 423 | + } else { | ||
| 424 | + ft.attach(newTab.fragment); | ||
| 425 | + } | ||
| 426 | + } | ||
| 427 | + | ||
| 428 | + mLastTab = newTab; | ||
| 429 | + } | ||
| 430 | + return ft; | ||
| 431 | + } | ||
| 432 | +} |
app/src/main/res/drawable-hdpi/tab_bar_bg.9.png
0 → 100644
2.75 KB
app/src/main/res/drawable-mdpi/tab_bar_bg.9.png
0 → 100644
1.68 KB
app/src/main/res/drawable-xhdpi/tab_bar_bg.9.png
0 → 100644
4.29 KB
app/src/main/res/drawable-xxhdpi/tab_bar_bg.9.png
0 → 100644
7.34 KB
app/src/main/res/drawable-xxxhdpi/tab_bar_bg.9.png
0 → 100644
13.4 KB
app/src/main/res/drawable/tab_camera_selector.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | + <!-- Non focused states --> | ||
| 4 | + <item android:drawable="@drawable/ic_camera_sel" android:state_focused="false" android:state_pressed="false" android:state_selected="false" /> | ||
| 5 | + <item android:drawable="@drawable/ic_camera" android:state_focused="false" android:state_pressed="false" android:state_selected="true" /> | ||
| 6 | + <!-- Focused states --> | ||
| 7 | + <item android:drawable="@drawable/ic_camera" android:state_focused="true" android:state_pressed="false" android:state_selected="false" /> | ||
| 8 | + <item android:drawable="@drawable/ic_camera" android:state_focused="true" android:state_pressed="false" android:state_selected="true" /> | ||
| 9 | + <!-- Pressed --> | ||
| 10 | + <item android:drawable="@drawable/ic_camera" android:state_pressed="true" android:state_selected="true" /> | ||
| 11 | + <item android:drawable="@drawable/ic_camera" android:state_pressed="true" /> | ||
| 12 | + | ||
| 13 | +</selector> | ||
| 0 | \ No newline at end of file | 14 | \ No newline at end of file |
app/src/main/res/drawable/tab_home_selector.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | + <!-- Non focused states --> | ||
| 4 | + <item android:drawable="@drawable/ic_home" android:state_focused="false" android:state_pressed="false" android:state_selected="false" /> | ||
| 5 | + <item android:drawable="@drawable/ic_home_sel" android:state_focused="false" android:state_pressed="false" android:state_selected="true" /> | ||
| 6 | + <!-- Focused states --> | ||
| 7 | + <item android:drawable="@drawable/ic_home_sel" android:state_focused="true" android:state_pressed="false" android:state_selected="false" /> | ||
| 8 | + <item android:drawable="@drawable/ic_home_sel" android:state_focused="true" android:state_pressed="false" android:state_selected="true" /> | ||
| 9 | + <!-- Pressed --> | ||
| 10 | + <item android:drawable="@drawable/ic_home_sel" android:state_pressed="true" android:state_selected="true" /> | ||
| 11 | + <item android:drawable="@drawable/ic_home_sel" android:state_pressed="true" /> | ||
| 12 | + | ||
| 13 | +</selector> | ||
| 0 | \ No newline at end of file | 14 | \ No newline at end of file |
app/src/main/res/drawable/tab_item_text.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | + <!-- Non focused states --> | ||
| 4 | + <item android:color="#323333" android:state_focused="false" android:state_pressed="false" android:state_selected="false" /> | ||
| 5 | + <item android:color="#EA002A" android:state_focused="false" android:state_pressed="false" android:state_selected="true" /> | ||
| 6 | + <!-- Focused states --> | ||
| 7 | + <item android:color="#EA002A" android:state_focused="true" android:state_pressed="false" android:state_selected="false" /> | ||
| 8 | + <item android:color="#EA002A" android:state_focused="true" android:state_pressed="false" android:state_selected="true" /> | ||
| 9 | + <!-- Pressed --> | ||
| 10 | + <item android:color="#EA002A" android:state_pressed="true" android:state_selected="true" /> | ||
| 11 | + <item android:color="#EA002A" android:state_pressed="true" /> | ||
| 12 | +</selector> | ||
| 0 | \ No newline at end of file | 13 | \ No newline at end of file |
app/src/main/res/drawable/tab_live_tv_selector.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | + <!-- Non focused states --> | ||
| 4 | + <item android:drawable="@drawable/ic_live_tv" android:state_focused="false" android:state_pressed="false" android:state_selected="false" /> | ||
| 5 | + <item android:drawable="@drawable/ic_live_tv_sel" android:state_focused="false" android:state_pressed="false" android:state_selected="true" /> | ||
| 6 | + <!-- Focused states --> | ||
| 7 | + <item android:drawable="@drawable/ic_live_tv_sel" android:state_focused="true" android:state_pressed="false" android:state_selected="false" /> | ||
| 8 | + <item android:drawable="@drawable/ic_live_tv_sel" android:state_focused="true" android:state_pressed="false" android:state_selected="true" /> | ||
| 9 | + <!-- Pressed --> | ||
| 10 | + <item android:drawable="@drawable/ic_live_tv_sel" android:state_pressed="true" android:state_selected="true" /> | ||
| 11 | + <item android:drawable="@drawable/ic_live_tv_sel" android:state_pressed="true" /> | ||
| 12 | + | ||
| 13 | +</selector> | ||
| 0 | \ No newline at end of file | 14 | \ No newline at end of file |
app/src/main/res/drawable/tab_person_selector.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | + <!-- Non focused states --> | ||
| 4 | + <item android:drawable="@drawable/ic_person" android:state_focused="false" android:state_pressed="false" android:state_selected="false" /> | ||
| 5 | + <item android:drawable="@drawable/ic_person_sel" android:state_focused="false" android:state_pressed="false" android:state_selected="true" /> | ||
| 6 | + <!-- Focused states --> | ||
| 7 | + <item android:drawable="@drawable/ic_person_sel" android:state_focused="true" android:state_pressed="false" android:state_selected="false" /> | ||
| 8 | + <item android:drawable="@drawable/ic_person_sel" android:state_focused="true" android:state_pressed="false" android:state_selected="true" /> | ||
| 9 | + <!-- Pressed --> | ||
| 10 | + <item android:drawable="@drawable/ic_person_sel" android:state_pressed="true" android:state_selected="true" /> | ||
| 11 | + <item android:drawable="@drawable/ic_person_sel" android:state_pressed="true" /> | ||
| 12 | + | ||
| 13 | +</selector> | ||
| 0 | \ No newline at end of file | 14 | \ No newline at end of file |
app/src/main/res/drawable/tab_videocam_selector.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | + <!-- Non focused states --> | ||
| 4 | + <item android:drawable="@drawable/ic_videocam" android:state_focused="false" android:state_pressed="false" android:state_selected="false" /> | ||
| 5 | + <item android:drawable="@drawable/ic_videocam_sel" android:state_focused="false" android:state_pressed="false" android:state_selected="true" /> | ||
| 6 | + <!-- Focused states --> | ||
| 7 | + <item android:drawable="@drawable/ic_videocam_sel" android:state_focused="true" android:state_pressed="false" android:state_selected="false" /> | ||
| 8 | + <item android:drawable="@drawable/ic_videocam_sel" android:state_focused="true" android:state_pressed="false" android:state_selected="true" /> | ||
| 9 | + <!-- Pressed --> | ||
| 10 | + <item android:drawable="@drawable/ic_videocam_sel" android:state_pressed="true" android:state_selected="true" /> | ||
| 11 | + <item android:drawable="@drawable/ic_videocam_sel" android:state_pressed="true" /> | ||
| 12 | + | ||
| 13 | +</selector> | ||
| 0 | \ No newline at end of file | 14 | \ No newline at end of file |
app/src/main/res/layout/activity_main.xml
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | -<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | - xmlns:tools="http://schemas.android.com/tools" | ||
| 4 | - android:layout_width="match_parent" | ||
| 5 | - android:layout_height="match_parent" | ||
| 6 | - tools:context="com.cnlive.gundam.MainActivity"> | 2 | +<layout xmlns:android="http://schemas.android.com/apk/res/android" |
| 3 | + xmlns:app="http://schemas.android.com/apk/res-auto"> | ||
| 7 | 4 | ||
| 5 | + <data> | ||
| 8 | 6 | ||
| 9 | -</android.support.constraint.ConstraintLayout> | 7 | + <variable |
| 8 | + name="onSetCurrentTabListener" | ||
| 9 | + type="com.cnlive.gundam.main.ui.widget.FragmentTabHost.OnSetCurrentTabListener" /> | ||
| 10 | + <variable | ||
| 11 | + name="contentId" | ||
| 12 | + type="int"/> | ||
| 13 | + <variable | ||
| 14 | + name="tabItemInfoList" | ||
| 15 | + type="java.util.List<com.cnlive.gundam.main.ui.widget.FragmentTabHost.TabItemInfo>"/> | ||
| 16 | + </data> | ||
| 17 | + | ||
| 18 | + <RelativeLayout | ||
| 19 | + android:layout_width="match_parent" | ||
| 20 | + android:layout_height="match_parent" | ||
| 21 | + android:orientation="vertical"> | ||
| 22 | + | ||
| 23 | + <FrameLayout | ||
| 24 | + android:id="@+id/realtabcontent" | ||
| 25 | + android:layout_width="match_parent" | ||
| 26 | + android:layout_height="match_parent" | ||
| 27 | + android:layout_marginBottom="54dp" /> | ||
| 28 | + | ||
| 29 | + <com.cnlive.gundam.main.ui.widget.FragmentTabHost | ||
| 30 | + android:id="@+id/tabhost" | ||
| 31 | + android:layout_width="match_parent" | ||
| 32 | + android:layout_height="70dp" | ||
| 33 | + android:layout_alignParentBottom="true" | ||
| 34 | + android:background="@drawable/tab_bar_bg" | ||
| 35 | + app:dividerDrawable="@null" | ||
| 36 | + app:onSetCurrentTabListener="@{onSetCurrentTabListener}" | ||
| 37 | + app:contentId="@{contentId}" | ||
| 38 | + app:tabItemList="@{tabItemInfoList}"> | ||
| 39 | + | ||
| 40 | + <FrameLayout | ||
| 41 | + android:id="@android:id/tabcontent" | ||
| 42 | + android:layout_width="0dip" | ||
| 43 | + android:layout_height="0dip" | ||
| 44 | + android:layout_weight="0" /> | ||
| 45 | + </com.cnlive.gundam.main.ui.widget.FragmentTabHost> | ||
| 46 | + | ||
| 47 | + </RelativeLayout> | ||
| 48 | +</layout> | ||
| 10 | \ No newline at end of file | 49 | \ No newline at end of file |
app/src/main/res/layout/indicator_main_home.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + android:layout_width="match_parent" | ||
| 4 | + android:layout_height="64dp"> | ||
| 5 | + | ||
| 6 | + <ImageView | ||
| 7 | + android:id="@+id/tabImg" | ||
| 8 | + android:layout_width="32dp" | ||
| 9 | + android:layout_height="32dp" | ||
| 10 | + android:layout_above="@+id/tabText" | ||
| 11 | + android:layout_centerHorizontal="true" | ||
| 12 | + android:contentDescription="@null" | ||
| 13 | + android:src="@drawable/tab_home_selector" /> | ||
| 14 | + | ||
| 15 | + <TextView | ||
| 16 | + android:id="@+id/tabText" | ||
| 17 | + android:layout_width="wrap_content" | ||
| 18 | + android:layout_height="16dp" | ||
| 19 | + android:layout_alignParentBottom="true" | ||
| 20 | + android:layout_centerHorizontal="true" | ||
| 21 | + android:layout_marginBottom="4dp" | ||
| 22 | + android:focusable="true" | ||
| 23 | + android:gravity="center_vertical" | ||
| 24 | + android:text="@string/main_tab_home" | ||
| 25 | + android:textColor="@drawable/tab_item_text" | ||
| 26 | + android:textSize="12sp" /> | ||
| 27 | +</RelativeLayout> | ||
| 0 | \ No newline at end of file | 28 | \ No newline at end of file |
app/src/main/res/layout/indicator_main_live.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + android:layout_width="match_parent" | ||
| 4 | + android:layout_height="64dp"> | ||
| 5 | + | ||
| 6 | + <ImageView | ||
| 7 | + android:id="@+id/tabImg" | ||
| 8 | + android:layout_width="32dp" | ||
| 9 | + android:layout_height="32dp" | ||
| 10 | + android:layout_above="@+id/tabText" | ||
| 11 | + android:layout_centerHorizontal="true" | ||
| 12 | + android:contentDescription="@null" | ||
| 13 | + android:src="@drawable/tab_videocam_selector" /> | ||
| 14 | + | ||
| 15 | + <TextView | ||
| 16 | + android:id="@+id/tabText" | ||
| 17 | + android:layout_width="wrap_content" | ||
| 18 | + android:layout_height="16dp" | ||
| 19 | + android:layout_alignParentBottom="true" | ||
| 20 | + android:layout_centerHorizontal="true" | ||
| 21 | + android:layout_marginBottom="4dp" | ||
| 22 | + android:focusable="true" | ||
| 23 | + android:gravity="center_vertical" | ||
| 24 | + android:text="@string/main_tab_live" | ||
| 25 | + android:textColor="@drawable/tab_item_text" | ||
| 26 | + android:textSize="12sp" /> | ||
| 27 | +</RelativeLayout> | ||
| 0 | \ No newline at end of file | 28 | \ No newline at end of file |
app/src/main/res/layout/indicator_main_live_tv.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + android:layout_width="match_parent" | ||
| 4 | + android:layout_height="64dp"> | ||
| 5 | + | ||
| 6 | + <ImageView | ||
| 7 | + android:id="@+id/tabImg" | ||
| 8 | + android:layout_width="32dp" | ||
| 9 | + android:layout_height="32dp" | ||
| 10 | + android:layout_above="@+id/tabText" | ||
| 11 | + android:layout_centerHorizontal="true" | ||
| 12 | + android:contentDescription="@null" | ||
| 13 | + android:src="@drawable/tab_live_tv_selector" /> | ||
| 14 | + | ||
| 15 | + <TextView | ||
| 16 | + android:id="@+id/tabText" | ||
| 17 | + android:layout_width="wrap_content" | ||
| 18 | + android:layout_height="16dp" | ||
| 19 | + android:layout_alignParentBottom="true" | ||
| 20 | + android:layout_centerHorizontal="true" | ||
| 21 | + android:layout_marginBottom="4dp" | ||
| 22 | + android:focusable="true" | ||
| 23 | + android:gravity="center_vertical" | ||
| 24 | + android:text="@string/main_tab_live_tv" | ||
| 25 | + android:textColor="@drawable/tab_item_text" | ||
| 26 | + android:textSize="12sp" /> | ||
| 27 | +</RelativeLayout> | ||
| 0 | \ No newline at end of file | 28 | \ No newline at end of file |
app/src/main/res/layout/indicator_main_mine.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + android:layout_width="match_parent" | ||
| 4 | + android:layout_height="64dp"> | ||
| 5 | + | ||
| 6 | + <ImageView | ||
| 7 | + android:id="@+id/tabImg" | ||
| 8 | + android:layout_width="32dp" | ||
| 9 | + android:layout_height="32dp" | ||
| 10 | + android:layout_above="@+id/tabText" | ||
| 11 | + android:layout_centerHorizontal="true" | ||
| 12 | + android:contentDescription="@null" | ||
| 13 | + android:src="@drawable/tab_person_selector" /> | ||
| 14 | + | ||
| 15 | + <TextView | ||
| 16 | + android:id="@+id/tabText" | ||
| 17 | + android:layout_width="wrap_content" | ||
| 18 | + android:layout_height="16dp" | ||
| 19 | + android:layout_alignParentBottom="true" | ||
| 20 | + android:layout_centerHorizontal="true" | ||
| 21 | + android:layout_marginBottom="4dp" | ||
| 22 | + android:focusable="true" | ||
| 23 | + android:gravity="center_vertical" | ||
| 24 | + android:text="@string/main_tab_mine" | ||
| 25 | + android:textColor="@drawable/tab_item_text" | ||
| 26 | + android:textSize="12sp" /> | ||
| 27 | +</RelativeLayout> | ||
| 0 | \ No newline at end of file | 28 | \ No newline at end of file |
app/src/main/res/layout/indicator_main_stream.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + android:layout_width="match_parent" | ||
| 4 | + android:layout_height="64dp"> | ||
| 5 | + | ||
| 6 | + <ImageView | ||
| 7 | + android:id="@+id/tabImg" | ||
| 8 | + android:layout_width="64dp" | ||
| 9 | + android:layout_height="64dp" | ||
| 10 | + android:layout_alignParentBottom="true" | ||
| 11 | + android:layout_centerHorizontal="true" | ||
| 12 | + android:contentDescription="@null" | ||
| 13 | + android:src="@drawable/tab_camera_selector" /> | ||
| 14 | +</RelativeLayout> | ||
| 0 | \ No newline at end of file | 15 | \ No newline at end of file |
app/src/main/res/values/strings.xml
| 1 | <resources> | 1 | <resources> |
| 2 | <string name="app_name">CNLiveApp</string> | 2 | <string name="app_name">CNLiveApp</string> |
| 3 | + | ||
| 4 | + <string name="main_tab_home">首页</string> | ||
| 5 | + <string name="main_tab_live_tv">电视台</string> | ||
| 6 | + <string name="main_tab_live">直播</string> | ||
| 7 | + <string name="main_tab_mine">我的</string> | ||
| 3 | </resources> | 8 | </resources> |
app/src/main/res/values/styles.xml
| @@ -8,4 +8,7 @@ | @@ -8,4 +8,7 @@ | ||
| 8 | <item name="colorAccent">@color/colorAccent</item> | 8 | <item name="colorAccent">@color/colorAccent</item> |
| 9 | </style> | 9 | </style> |
| 10 | 10 | ||
| 11 | + <declare-styleable name="FragmentTabHost"> | ||
| 12 | + <attr name="dividerDrawable" format="reference" /> | ||
| 13 | + </declare-styleable> | ||
| 11 | </resources> | 14 | </resources> |