一、ViewPagerIndicatorjava
https://github.com/JakeWharton/ViewPagerIndicatorandroid
package com.viewpagerindicator.sample; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import com.viewpagerindicator.TabPageIndicator; public class SampleTabsDefault extends FragmentActivity { private static final String[] CONTENT = new String[] { "Recent", "Artists", "Albums", "Songs", "Playlists", "Genres" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simple_tabs); FragmentPagerAdapter adapter = new GoogleMusicAdapter(getSupportFragmentManager()); ViewPager pager = (ViewPager)findViewById(R.id.pager); pager.setAdapter(adapter); TabPageIndicator indicator = (TabPageIndicator)findViewById(R.id.indicator); indicator.setViewPager(pager); } class GoogleMusicAdapter extends FragmentPagerAdapter { public GoogleMusicAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return TestFragment.newInstance(CONTENT[position % CONTENT.length]); } @Override public CharSequence getPageTitle(int position) { return CONTENT[position % CONTENT.length].toUpperCase(); } @Override public int getCount() { return CONTENT.length; } } }
修改庫文件的樣式、文字等git
<?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2008 The Android Open Source Project 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. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Non focused states --> <item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@android:color/transparent" /> <item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/news_tab_item_bg_select" /> <!-- Focused states --> <item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@android:color/transparent" /> <item android:state_focused="true" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/news_tab_item_bg_select" /> <!-- Pressed --> <!-- Non focused states --> <item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@android:color/transparent" /> <item android:state_focused="false" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/news_tab_item_bg_select" /> <!-- Focused states --> <item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@android:color/transparent" /> <item android:state_focused="true" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/news_tab_item_bg_select" /> </selector>
<?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2011 Jake Wharton 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. --> <resources> <style name="Theme.PageIndicatorDefaults" parent="android:Theme"> <item name="vpiIconPageIndicatorStyle">@style/Widget.IconPageIndicator</item> <item name="vpiTabPageIndicatorStyle">@style/Widget.TabPageIndicator</item> </style> <style name="Widget"> </style> <style name="Widget.TabPageIndicator" parent="Widget"> <item name="android:gravity">center</item> <item name="android:background">@drawable/vpi__tab_indicator</item> <item name="android:paddingLeft">22dip</item> <item name="android:paddingRight">22dip</item> <item name="android:paddingTop">12dp</item> <item name="android:paddingBottom">12dp</item> <item name="android:textAppearance">@style/TextAppearance.TabPageIndicator</item> <item name="android:textSize">16sp</item> <item name="android:maxLines">1</item> </style> <style name="TextAppearance.TabPageIndicator" parent="Widget"> <item name="android:textStyle">bold</item> <item name="android:textColor">@color/vpi__dark_theme</item> </style> <style name="Widget.IconPageIndicator" parent="Widget"> <item name="android:layout_marginLeft">6dp</item> <item name="android:layout_marginRight">6dp</item> </style> </resources>
<?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:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <com.viewpagerindicator.TabPageIndicator android:id="@+id/indicator" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <ImageView android:id="@+id/iv_next_page" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:padding="10dp" android:src="@drawable/news_cate_arr" /> </LinearLayout> <android.support.v4.view.ViewPager android:id="@+id/vp_news_detail" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
import android.app.Activity; import android.graphics.Color; import android.view.Gravity; import android.view.View; import android.widget.TextView; import com.itheima.zhsh66.base.BaseMenuDetailPager; import com.itheima.zhsh66.domain.NewsMenuData.NewsTabData; /** * 12個頁籤的頁面對象 * */ public class TabDetailPager extends BaseMenuDetailPager { private NewsTabData mTabData; private TextView mTextView; public TabDetailPager(Activity activity, NewsTabData tabData) { super(activity); mTabData = tabData; } @Override public View initView() { mTextView = new TextView(mActivity); mTextView.setTextColor(Color.RED); mTextView.setTextSize(22); mTextView.setGravity(Gravity.CENTER); return mTextView; } @Override public void initData() { mTextView.setText(mTabData.title); } }
import java.util.ArrayList; import android.app.Activity; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.View; import android.view.ViewGroup; import com.itheima.zhsh66.MainActivity; import com.itheima.zhsh66.R; import com.itheima.zhsh66.base.BaseMenuDetailPager; import com.itheima.zhsh66.domain.NewsMenuData.NewsTabData; import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu; import com.lidroid.xutils.ViewUtils; import com.lidroid.xutils.view.annotation.ViewInject; import com.lidroid.xutils.view.annotation.event.OnClick; import com.viewpagerindicator.TabPageIndicator; /** * 菜單詳情頁-新聞 * * ViewPagerIndicator使用流程: 1. 引入Library庫 2. 佈局文件中配置TabPageIndicator 3. * 將指針和Viewpager關聯起來 4. 重寫getPageTitle方法,返回每一個頁面的標題(PagerAdapter) 5. * 設置activity主題樣式 6. 修改源碼中的樣式(修改圖片, 文字顏色) * */ public class NewsMenuDetailPager extends BaseMenuDetailPager implements OnPageChangeListener { @ViewInject(R.id.vp_news_detail) private ViewPager mViewPager; @ViewInject(R.id.indicator) private TabPageIndicator mIndicator; private ArrayList<NewsTabData> mTabList;// 頁籤網絡數據集合 private ArrayList<TabDetailPager> mTabPagers;// 頁籤頁面集合 public NewsMenuDetailPager(Activity activity, ArrayList<NewsTabData> children) { super(activity); mTabList = children; } @Override public View initView() { View view = View.inflate(mActivity, R.layout.pager_menu_detail_news, null); ViewUtils.inject(this, view); return view; } @Override public void initData() { // 初始化12個頁籤 mTabPagers = new ArrayList<TabDetailPager>(); for (NewsTabData tabData : mTabList) { // 建立一個頁籤對象 TabDetailPager pager = new TabDetailPager(mActivity, tabData); mTabPagers.add(pager); } mViewPager.setAdapter(new NewsMenuAdapter()); // mViewPager.setOnPageChangeListener(this); // 此方法在viewpager設置完數據以後再調用 mIndicator.setViewPager(mViewPager);// 將頁面指示器和ViewPager關聯起來 mIndicator.setOnPageChangeListener(this);// 當viewpager和指針綁定時,須要將頁面切換監聽設置給指針 } class NewsMenuAdapter extends PagerAdapter { // 返回頁面指示器的標題 @Override public CharSequence getPageTitle(int position) { return mTabList.get(position).title; } @Override public int getCount() { return mTabPagers.size(); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public Object instantiateItem(ViewGroup container, int position) { TabDetailPager pager = mTabPagers.get(position); container.addView(pager.mRootView); pager.initData();// 初始化數據 return pager.mRootView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { System.out.println("position:" + position); if (position == 0) {// 在第一個頁籤,容許側邊欄出現 // 開啓側邊欄 setSlidingMenuEnable(true); } else {// 其餘頁籤,禁用側邊欄, 保證viewpager能夠正常向右滑動 // 關閉側邊欄 setSlidingMenuEnable(false); } } @Override public void onPageScrollStateChanged(int state) { } /** * 設置側邊欄可用不可用 * * @param enable */ private void setSlidingMenuEnable(boolean enable) { MainActivity mainUI = (MainActivity) mActivity; SlidingMenu slidingMenu = mainUI.getSlidingMenu(); if (enable) { slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN); } else { // 禁用掉側邊欄滑動效果 slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_NONE); } } @OnClick(R.id.iv_next_page) public void nextPage(View view) { int currentItem = mViewPager.getCurrentItem(); currentItem++; mViewPager.setCurrentItem(currentItem); } }
二、對於不能滑動的ViewPager嵌套ViewPager,容許嵌套的ViewPager滑動github
import android.content.Context; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; /** * 不能滑動的ViewPager * */ public class NoScrollViewPager extends ViewPager { public NoScrollViewPager(Context context, AttributeSet attrs) { super(context, attrs); } public NoScrollViewPager(Context context) { super(context); } //決定事件是否中斷 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return false;//不攔截事件, 讓嵌套的子viewpager有機會響應觸摸事件 } @Override public boolean onTouchEvent(MotionEvent ev) { // 重寫ViewPager滑動事件, 改成什麼都不作 return true; } }
三、viewPager嵌套,子viewPager是否攔截父viewPager的事件express
import android.content.Context; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; /** * 頭條新聞ViewPager * */ public class HorizontalScrollViewPager extends ViewPager { int startX; int startY; public HorizontalScrollViewPager(Context context, AttributeSet attrs) { super(context, attrs); } public HorizontalScrollViewPager(Context context) { super(context); } /** * 分狀況決定父控件是否須要攔截事件 * * 1. 上下划動須要攔截 2. 向右劃&第一個頁面,須要攔截 3. 向左劃&最後一個頁面, 須要攔截 */ @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: startX = (int) ev.getX(); startY = (int) ev.getY(); // 請求父控件及祖宗控件不要攔截事件 getParent().requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_MOVE: int endX = (int) ev.getX(); int endY = (int) ev.getY(); int dx = endX - startX; int dy = endY - startY; if (Math.abs(dx) > Math.abs(dy)) {// 左右劃 if (dx > 0) {// 向右滑動 if (this.getCurrentItem() == 0) { // 第一個頁面 // 請求父控件及祖宗控件攔截事件 getParent().requestDisallowInterceptTouchEvent(false); } } else { // 向左滑動 if (getCurrentItem() == this.getAdapter().getCount() - 1) { // 最後一個item // 請求父控件及祖宗控件攔截事件 getParent().requestDisallowInterceptTouchEvent(false); } } } else { // 上下滑動 // 請求父控件及祖宗控件攔截事件 getParent().requestDisallowInterceptTouchEvent(false); } break; default: break; } return super.dispatchTouchEvent(ev); } }
四、ViewPagerIndicator應用apache
protected void processResult(String result) { Gson gson = new Gson(); mNewsTabData = gson.fromJson(result, NewsData.class); // 初始化頭條新聞 mTopNewsList = mNewsTabData.data.topnews; if (mTopNewsList != null) { mTopNewsAdapter = new TopNewsAdapter(); mViewPager.setAdapter(mTopNewsAdapter); mIndicator.setViewPager(mViewPager);// 將指示器和viewpager綁定 mIndicator.setSnap(true);// 快照模式 mIndicator.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { System.out.println("position:" + position); TopNews topNews = mTopNewsList.get(position); tvTopNewsTitle.setText(topNews.title); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageScrollStateChanged(int state) { } }); mIndicator.onPageSelected(0);// 將小圓點位置歸零, 解決它會在頁面銷燬時仍記錄上次位置的bug tvTopNewsTitle.setText(mTopNewsList.get(0).title);// 初始化第一頁標題 } // 初始化新聞列表 mNewsList = mNewsTabData.data.news; if (mNewsList != null) { mNewsAdapter = new NewsAdapter(); lvList.setAdapter(mNewsAdapter); } }