編輯:關於Android編程
今天發布本文的原因是應一個網友要求,就是實現局部的圖片滑動指引效果。這種效果一般是在新聞客戶端上比較常見,其功能是:
1、頂部單張圖片左右拖拉滑動;
2、帶指引;
3、僅滑動頂部單張圖片,不滑動頁面,下面的圖文內容不動;
4、類似於新聞客戶端的功能
為了大家能更好的理解,我們先來看下要實現的效果圖:
以上便是實現的效果圖,其實實現原理也並不難,我們只需要將android-support-v4.jar包中ViewPager控件設置成局部就可以,只是處理界面時稍微有點麻煩,不過看完本篇之後,大家以後使用時直接調用就行。也希望本篇能夠對大家有所幫助。
好了,下面讓我們開始我們的實現過程,主要給大家介紹一下實現步驟和一些核心代碼。首先我們需要將android-support-v4.jar添加到工程當中,然後讓我們看一下程序結構:
我先簡要介紹其實現原理:
在布局頁面中將設置成局部,限制其高度,然後為滑動的圖片集合生成布局界面,並在代碼中設置相應的數據適配器和監聽事件。在切換事件監聽器中更改相應的圓點圖片和顯示標題,由於滑動圖片下方的界面不需要改變內容,所以很很容易內容超過屏幕,所以需要設置ScrollView以在內容比較多時顯示滾動條,我會在下面介紹如何讓ViewPager和ScrollView結合使用。
先看下android.support.v4.view.ViewPager在布局界面中的核心代碼:
<android.support.v4.view.ViewPager android:id="@+id/image_slide_page" android:layout_width="fill_parent" android:layout_height="180dip" android:focusable="true" />
在程序結構中,MainActivity.java是啟動的Activity,而TopicNews.java是顯示頭條的Acitivity。在顯示時,我們需要將TopicNews.java中的對象進行初始化設置,如下代碼:
/** * 初始化 */ private void initeViews(){ // 滑動圖片區域 imagePageViews = new ArrayList<View>(); LayoutInflater inflater = getLayoutInflater(); main = (ViewGroup)inflater.inflate(R.layout.page_topic_news, null); viewPager = (ViewPager) main.findViewById(R.id.image_slide_page); // 圓點圖片區域 parser = new NewsXmlParser(); int length = parser.getSlideImages().length; imageCircleViews = new ImageView[length]; imageCircleView = (ViewGroup) main.findViewById(R.id.layout_circle_images); slideLayout = new SlideImageLayout(TopicNews.this); slideLayout.setCircleImageLayout(length); for(int i = 0;i < length;i++){ imagePageViews.add(slideLayout.getSlideImageLayout(parser.getSlideImages()[i])); imageCircleViews[i] = slideLayout.getCircleImageLayout(i); imageCircleView.addView(slideLayout.getLinearLayout(imageCircleViews[i], 10, 10)); } // 設置默認的滑動標題 tvSlideTitle = (TextView) main.findViewById(R.id.tvSlideTitle); tvSlideTitle.setText(parser.getSlideTitles()[0]); setContentView(main); // 設置ViewPager viewPager.setAdapter(new SlideImageAdapter()); viewPager.setOnPageChangeListener(new ImagePageChangeListener()); }
以上對象的聲明代碼如下所示:
// 滑動圖片的集合 private ArrayList<View> imagePageViews = null; private ViewGroup main = null; private ViewPager viewPager = null; // 當前ViewPager索引 private int pageIndex = 0; // 包含圓點圖片的View private ViewGroup imageCircleView = null; private ImageView[] imageCircleViews = null; // 滑動標題 private TextView tvSlideTitle = null; // 布局設置類 private SlideImageLayout slideLayout = null; // 數據解析類 private NewsXmlParser parser = null;
由於在顯示頭條的Activity即TopicNews中,設置布局文件不是直接設置的,也就是通過inflate將Layout轉化為View控件的,所以在使用page_topic_news.xml中的View時,需要通過main.findViewById(),即如下代碼所示:
main = (ViewGroup)inflater.inflate(R.layout.page_topic_news, null);
viewPager = (ViewPager) main.findViewById(R.id.image_slide_page);
而不能像這樣直接使用:
viewPager = (ViewPager) findViewById(R.id.image_slide_page);
這點大家在使用時需要注意。
NewsXmlParser類是用於對顯示的數據進行解析,由於本示例只是一個演示示例,所以在這個類裡我只是設置一些要顯示的固定數據,沒有設置動態數據,這點明白就可以,代碼如下:
package com.image.indicator.parser; import java.io.InputStream; import java.util.HashMap; import java.util.List; import org.xmlpull.v1.XmlPullParser; import android.util.Xml; import com.image.indicator.R; import com.image.indicator.entity.News; import com.image.indicator.utility.FileAccess; /** * 解析新聞數據列表 * @Description: 解析新聞數據列表,這裡只是個示例,具體地不再實現。 * @File: NewsXmlParser.java * @Package com.image.indicator.parser * @Author Hanyonglu * @Date 2012-6-18 下午02:31:26 * @Version V1.0 */ public class NewsXmlParser { // 新聞列表 private List<HashMap<String, News>> newsList = null; // 滑動圖片的集合,這裡設置成了固定加載,當然也可動態加載。 private int[] slideImages = { R.drawable.image01, R.drawable.image02, R.drawable.image03, R.drawable.image04, R.drawable.image05}; // 滑動標題的集合 private int[] slideTitles = { R.string.title1, R.string.title2, R.string.title3, R.string.title4, R.string.title5, }; // 滑動鏈接的集合 private String[] slideUrls = { "http://mobile.csdn.net/a/20120616/2806676.html", "http://cloud.csdn.net/a/20120614/2806646.html", "http://mobile.csdn.net/a/20120613/2806603.html", "http://news.csdn.net/a/20120612/2806565.html", "http://mobile.csdn.net/a/20120615/2806659.html", }; public int[] getSlideImages(){ return slideImages; } public int[] getSlideTitles(){ return slideTitles; } public String[] getSlideUrls(){ return slideUrls; } /** * 獲取XmlPullParser對象 * @param result * @return */ private XmlPullParser getXmlPullParser(String result){ XmlPullParser parser = Xml.newPullParser(); InputStream inputStream = FileAccess.String2InputStream(result); try { parser.setInput(inputStream, "UTF-8"); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } return parser; } public int getNewsListCount(String result){ int count = -1; try { XmlPullParser parser = getXmlPullParser(result); int event = parser.getEventType();//產生第一個事件 while(event != XmlPullParser.END_DOCUMENT){ switch(event){ case XmlPullParser.START_DOCUMENT: break; case XmlPullParser.START_TAG://判斷當前事件是否是標簽元素開始事件 if("count".equals(parser.getName())){//判斷開始標簽元素是否是count count = Integer.parseInt(parser.nextText()); } break; case XmlPullParser.END_TAG://判斷當前事件是否是標簽元素結束事件 // if("count".equals(parser.getName())){//判斷開始標簽元素是否是count // count = Integer.parseInt(parser.nextText()); // } break; } event = parser.next();//進入下一個元素並觸發相應事件 } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } // 無返回值,則返回-1 return count; } }
關於NewsXmlParser這個類,實現比較簡單,不再詳述,有興趣的朋友可以在開發過程中將其設置成動態數據並進行解析。
剛才在上面介紹其實現原理時,我提到需要設置滑動圖片集合的布局界面,那麼如何設置其布局呢?這裡我們需要用到SlideImageLayout。
SlideImageLayout類是用於生成滑動圖片區域布局和圓點圖片布局的類。我在上面的代碼中(即在TopicNews.java的初始化方法initeViews())使用for循環設置滑動圖片及圓點圖片的布局。在循環中就用到了getSlideImageLayout()、getCircleImageLayout()和getLinearLayout()這幾個方法。下面分別看下其功能,先看下getSlideImageLayout()實現代碼:
/** * 生成滑動圖片區域布局 * @param index * @return */ public View getSlideImageLayout(int index){ // 包含TextView的LinearLayout LinearLayout imageLinerLayout = new LinearLayout(activity); LinearLayout.LayoutParams imageLinerLayoutParames = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1); ImageView iv = new ImageView(activity); iv.setBackgroundResource(index); iv.setOnClickListener(new ImageOnClickListener()); imageLinerLayout.addView(iv,imageLinerLayoutParames); imageList.add(iv); return imageLinerLayout; }
由於滑動圖片一般需要設置其鏈接或是相應的ID,以便在點擊時轉向相應的Activity,顯示相應的內容或詳細信息。這裡我沒有過多的設置,只是在點擊時顯示標題及鏈接地址,代碼如下:
// 滑動頁面點擊事件監聽器 private class ImageOnClickListener implements OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub Toast.makeText(activity, parser.getSlideTitles()[pageIndex], Toast.LENGTH_SHORT).show(); Toast.makeText(activity, parser.getSlideUrls()[pageIndex], Toast.LENGTH_SHORT).show(); } }
getCircleImageLayout()方法主要是為圓點圖片生成相應的ImageView對象,代碼如下:
/** * 生成圓點圖片區域布局對象 * @param index * @return */ public ImageView getCircleImageLayout(int index){ imageView = new ImageView(activity); imageView.setLayoutParams(new LayoutParams(10,10)); imageView.setScaleType(ScaleType.FIT_XY); imageViews[index] = imageView; if (index == 0) { //默認選中第一張圖片 imageViews[index].setBackgroundResource(R.drawable.dot_selected); } else { imageViews[index].setBackgroundResource(R.drawable.dot_none); } return imageViews[index]; }
getLinearLayout()方法則是為圓點圖片添加相應的LinearLayout布局,以便設置圓點圖片之間的距離,代碼如下:
/** * 獲取LinearLayout * @param view * @param width * @param height * @return */ public View getLinearLayout(View view,int width,int height){ LinearLayout linerLayout = new LinearLayout(activity); LinearLayout.LayoutParams linerLayoutParames = new LinearLayout.LayoutParams( width, height, 1); // 這裡最好也自定義設置,有興趣的自己設置。 linerLayout.setPadding(10, 0, 10, 0); linerLayout.addView(view, linerLayoutParames); return linerLayout; }
getCircleImageLayout()和getLinearLayout()方法在NewsTopic.java中for循環的結構中結合代碼如下:
imageCircleViews[i] = slideLayout.getCircleImageLayout(i);
imageCircleView.addView(slideLayout.getLinearLayout(imageCircleViews[i], 10, 10));
這兩個方法結合使用便能優美地實現其圓點圖片的布局。
以上是關於NewsXmlParser和SlideImageLayout兩個類的介紹,下面讓我們再回到TopicNews類中繼續介紹相關知識。在TopicNews中進行對象初始化(initeViews()方法)以後,還需要設置ViewPager對象中的數據適配器和監聽事件。ViewPager中數據適配器的代碼如下:
// 滑動圖片數據適配器 private class SlideImageAdapter extends PagerAdapter { @Override public int getCount() { return imagePageViews.size(); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public int getItemPosition(Object object) { // TODO Auto-generated method stub return super.getItemPosition(object); } @Override public void destroyItem(View arg0, int arg1, Object arg2) { // TODO Auto-generated method stub ((ViewPager) arg0).removeView(imagePageViews.get(arg1)); } @Override public Object instantiateItem(View arg0, int arg1) { // TODO Auto-generated method stub ((ViewPager) arg0).addView(imagePageViews.get(arg1)); return imagePageViews.get(arg1); } @Override public void restoreState(Parcelable arg0, ClassLoader arg1) { // TODO Auto-generated method stub } @Override public Parcelable saveState() { // TODO Auto-generated method stub return null; } @Override public void startUpdate(View arg0) { // TODO Auto-generated method stub } @Override public void finishUpdate(View arg0) { // TODO Auto-generated method stub } }
而ViewPager的事件監聽器代碼如下:
// 滑動頁面更改事件監聽器 private class ImagePageChangeListener implements OnPageChangeListener { @Override public void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { // TODO Auto-generated method stub } @Override public void onPageSelected(int index) { pageIndex = index; slideLayout.setPageIndex(index); tvSlideTitle.setText(parser.getSlideTitles()[index]); for (int i = 0; i < imageCircleViews.length; i++) { imageCircleViews[index].setBackgroundResource(R.drawable.dot_selected); if (index != i) { imageCircleViews[i].setBackgroundResource(R.drawable.dot_none); } } } }
事件監聽器中主要在回調函數onPageSelected(int index)中變換標題和圓點圖片。
由於滑動區域下方的內容是不變的,也就是不滑動的,正如在我在上面提到的,內容可能會超出屏幕的范圍,所以我們需要使用ScrollView以便內容過多的時候顯示滾動條。可能一部分朋友會想到,要顯示滾動條我也知道使用ScrollView。我想在這裡說的是,這裡即有ViewPager控件,也有ScrollView,如果兩個View單獨使用不會有什麼問題。然而不幸的是,兩個一結合使用就出現了問題。什麼問題呢?就是在滑動圖片時出現反彈的現象,就是在滑動時很難滑動,我滑動時感覺很吃力,而且圖片就是滑動不過去,這個就是兩個View之間的沖突,因為兩個View都是滑動的View,都會計算相應的位置和判斷相應的距離。
我們如何來解決這個沖突呢?這裡我們需要重寫ScrollView的onInterceptTouchEvent()回調函數。需要在程序裡新加一個ScrollViewExtend類並繼承自ScrollView,下面是其代碼:
package com.image.indicator.control; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.ScrollView; /** * 能夠兼容ViewPager的ScrollView * @Description: 解決了ViewPager在ScrollView中的滑動反彈問題 * @File: ScrollViewExtend.java * @Package com.image.indicator.control * @Author Hanyonglu * @Date 2012-6-18 下午01:34:50 * @Version V1.0 */ public class ScrollViewExtend extends ScrollView { // 滑動距離及坐標 private float xDistance, yDistance, xLast, yLast; public ScrollViewExtend(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: xDistance = yDistance = 0f; xLast = ev.getX(); yLast = ev.getY(); break; case MotionEvent.ACTION_MOVE: final float curX = ev.getX(); final float curY = ev.getY(); xDistance += Math.abs(curX - xLast); yDistance += Math.abs(curY - yLast); xLast = curX; yLast = curY; if(xDistance > yDistance){ return false; } } return super.onInterceptTouchEvent(ev); } }
然後在我們的布局代碼中添加這個擴展的View,如下代碼:
<com.image.indicator.control.ScrollViewExtend android:layout_width="match_parent" android:layout_height="fill_parent"> …… </com.image.indicator.control.ScrollViewExtend>
以上的操作便可解決ViewPager和ScrollView之間沖突問題,這樣便可使用滾動條順利顯示下方不變的內容。在這裡再次給大家說明一下,由於本示例只是個演示示例,所以在滑動圖片的下方,我只是用了一張圖片固定地顯示頭條Activity的下方。當然有需要的朋友,可以將其進行改造,將滑動圖片的下方區域添加個ListView等View之類的以顯示相應要求的信息。
一些朋友可能會注意到,在滑動圖片區域的下方有一段透明的效果,如下圖所示:
這個實現也不難,只是在相應的布局代碼中添加background屬性即可,如下:
android:background="#55000000"
當然,透明度的設置有個范圍,有興趣的朋友到網上查找一下,這裡不再詳述。
本示例除了實現Android局部圖片滑動指引效果以外,還實現了上方導航菜單切換的效果,關於這個效果並不稀奇,因為網上有一些人已經實現該功能。不過在這裡,我跟他們做不太一樣的是,點擊上方的新聞分類時靈敏度比較好,也就是說點中的概率比較大。因為上方的新聞分類文字比較小,要想點中有時不是件容易的事。下面簡要說一下其實現過程及相應的代碼。
由於要在點擊新聞類別時背景圖片需要動畫效果,所以我添加了一個類:ImageAnimatioin,用於處理圖片移動時動畫效果。其
代碼如下:
/** * 設置圖像移動動畫效果 * @param v * @param startX * @param toX * @param startY * @param toY */ public static void SetImageSlide(View v, int startX, int toX, int startY, int toY) { TranslateAnimation anim = new TranslateAnimation(startX, toX, startY, toY); anim.setDuration(100); anim.setFillAfter(true); v.startAnimation(anim); }
下面展示一下點擊新聞類別時的事件監聽器中的代碼,因為在這個過程中需要計算移動圖片的位置和切換下面的主體內容,如下:
// 新聞分類事件監聽器 private class ItemOnclickListener implements OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub itemWidth = findViewById(R.id.layout).getWidth(); switch (v.getId()) { case R.id.tv_title_news: ImageAnimatioin.SetImageSlide(tvSelectedItem, startX, 0, 0, 0); startX = 0; tvSelectedItem.setText(R.string.title_news_category_tops); // 顯示頭條信息 intent.setClass(MainActivity.this, TopicNews.class); vNewsMain = getLocalActivityManager().startActivity( "TopicNews", intent).getDecorView(); break; case R.id.tv_title_info: ImageAnimatioin.SetImageSlide(tvSelectedItem, startX, itemWidth, 0, 0); startX = itemWidth; tvSelectedItem.setText(R.string.title_news_category_info); // 顯示資訊信息 intent.setClass(MainActivity.this, InfoNews.class); vNewsMain = getLocalActivityManager().startActivity( "InfoNews", intent).getDecorView(); break; case R.id.tv_title_blog: ImageAnimatioin.SetImageSlide(tvSelectedItem, startX, itemWidth * 2, 0, 0); startX = itemWidth * 2; tvSelectedItem.setText(R.string.title_news_category_blog); // 顯示博客信息 intent.setClass(MainActivity.this, BlogNews.class); vNewsMain = getLocalActivityManager().startActivity( "BlogNews", intent).getDecorView(); break; case R.id.tv_title_magazine: ImageAnimatioin.SetImageSlide(tvSelectedItem, startX, itemWidth * 3, 0, 0); startX = itemWidth * 3; tvSelectedItem.setText(R.string.title_news_category_magazine); // 顯示雜志信息 intent.setClass(MainActivity.this, MagazineNews.class); vNewsMain = getLocalActivityManager().startActivity( "MagazineNews", intent).getDecorView(); break; case R.id.tv_title_domain: ImageAnimatioin.SetImageSlide(tvSelectedItem, startX, itemWidth * 4, 0, 0); startX = itemWidth * 4; tvSelectedItem.setText(R.string.title_news_category_domain); // 顯示業界信息 intent.setClass(MainActivity.this, DomainNews.class); vNewsMain = getLocalActivityManager().startActivity( "DomainNews", intent).getDecorView(); break; case R.id.tv_title_more: ImageAnimatioin.SetImageSlide(tvSelectedItem, startX, itemWidth * 5, 0, 0); startX = itemWidth * 5; tvSelectedItem.setText(R.string.title_news_category_more); // 顯示更多信息 intent.setClass(MainActivity.this, MoreNews.class); vNewsMain = getLocalActivityManager().startActivity( "MoreNews", intent).getDecorView(); break; default: break; } // 更換Layout中的新聞主體 rlNewsMain.removeAllViews(); rlNewsMain.addView(vNewsMain, params); } }
這裡設置時是在一個主框架中變換新聞類別的布局,而不是直接顯示,所以需要注意下。另外,在點擊除頭條之外的新聞類別時,下方展示的也只是個圖片而已,有需要的朋友將其進行改造,這點不再多說。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
魅族的魅藍手機通常都是只有移動和聯通版兩種版本的,但是最近最新發布的魅藍E再次吧魅藍手機推向了一個新的高度,很多機友就開始問小編了。魅族魅藍E支持什麼SIM
在Android系統API中,有兩個Camera類: android.graphics.Camera android.hardware.Camera 第二個應用於
IOS相比於Android,動畫效果是一方面優勢,IOS相機切換時滑動的動畫很不錯,看著是有一個3D的效果,而且變化感覺很自然。Android也可以通過Graphics下
閱讀本節內容前可先了解 apkplug基礎教程 本教程是基於apkplug V1.6.8 版本編寫 最新開發方式以官網為准 可下載最新的apkplugdemo源碼h