Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發筆記(一百二十四)更好看的圖像控件

Android開發筆記(一百二十四)更好看的圖像控件

編輯:關於Android編程

畫廊Gallery

Gallery是一個早期的畫廊控件,左右滑動手勢可展示內嵌的圖片列表,類似於一個平面的萬花筒。雖然Android現在將Gallery標記為Deprecation(表示已廢棄),建議開發者采用HorizontalScrollView或者ViewPager來代替,但是Gallery用來輪播圖片其實是個挺好的選擇,所以下面我們還是簡單介紹它的用法,並結合其它控件加深對圖像開發的理解。
Gallery的常用屬性說明如下:
spacing : 指定圖片之間的間隔大小。
unselectedAlpha : 指定未選定圖片的透明度。取值為0到1,0表示完全透明,1表示完全不透明。
Gallery的常用方法說明如下:
setSpacing : 設置圖片之間的間隔大小。
setUnselectedAlpha : 設置未選定圖片的透明度。
setAdapter : 設置圖像視圖的適配器。
getSelectedItemId : 獲取當前選中的圖像id。0表示第一個圖像。
setSelection : 設置當前選中第幾個圖像。
setOnItemClickListener : 設置單項的點擊監聽器。
現在我們結合Gallery與ImageView來觀看畫廊的相冊效果,首先放置一個FrameLayout布局,裡面放入一個Gallery控件與一個ImageView控件,其中ImageView控件要充滿整個屏幕,Gallery控件可放在屏幕上方或下方;然後監聽Gallery控件的單項點擊事件,點擊指定圖片項時,便給ImageView控件填充該圖片,也就是點小圖看大圖。
下面是Gallery與ImageView結合使用的效果截圖:
\
下面是Gallery與ImageView結合使用的代碼例子:
import com.example.exmcard.adapter.GalleryAdapter;
import com.example.exmcard.util.MetricsUtil;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Gallery;
import android.widget.ImageView;

@SuppressWarnings("deprecation")
public class GalleryActivity extends Activity implements OnItemClickListener {

	private ImageView iv_gallery;
	private Gallery gl_gallery;

	// 圖片數組
	private int[] mImageRes = {
			R.drawable.scene1, R.drawable.scene2,
			R.drawable.scene3, R.drawable.scene4,
			R.drawable.scene5, R.drawable.scene6
			};
	private int dip_pad;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_gallery);
		dip_pad = MetricsUtil.dip2px(this, 20);

		iv_gallery = (ImageView) findViewById(R.id.iv_gallery);
		iv_gallery.setImageResource(mImageRes[0]);

		gl_gallery = (Gallery) findViewById(R.id.gl_gallery);
		gl_gallery.setPadding(dip_pad, dip_pad, dip_pad, dip_pad);
		gl_gallery.setSpacing(dip_pad);
		gl_gallery.setUnselectedAlpha(0.5f);
		gl_gallery.setAdapter(new GalleryAdapter(this, mImageRes));
		gl_gallery.setOnItemClickListener(this);
	}

	@Override
	public void onItemClick(AdapterView parent, View view, int position, long id) {
		iv_gallery.setImageResource(mImageRes[position]);
	}

}

圖像切換ImageSwitcher

可能大家已經發現,前面Gallery與ImageView在切換大圖時比較生硬,前後兩張圖片閃一下就切過去,用戶體驗不夠友好。那有沒有辦法讓圖片切換自然些呢,比如說通過漸變動畫的方式?答案肯定是有的,就是把ImageView換成ImageSwitcher,通過ImageSwitcher控件來實現圖片的切換動畫。ImageSwitcher實質是個視圖動畫師ViewAnimator,用於處理前後圖像的變換動畫;與之對應的是,TextSwitcher用於處理前後文本的變換動畫;另外ViewFlipper也是從ViewAnimator派生而來,則是用於處理兩個頁面視圖的變換動畫。有關ViewFlipper的詳細介紹參見《Android開發筆記(二十一)橫幅輪播頁》。
ImageSwitcher的常用方法說明如下:
setFactory : 設置一個視圖工廠。該視圖工廠對象從ViewFactory派生而來,內部需要重寫makeView方法來返回視圖工廠裡的具體視圖。對於ImageSwitcher來說,視圖工廠應當返回的當然是ImageView對象了。
setImageResource : 設置當前圖像的資源ID。該方法與下面的setImageDrawable和setImageURI為三選一操作,調用了其中一個方法,就無需調用另外兩個方法。
setImageDrawable : 設置當前圖像的Drawable對象。
setImageURI : 設置當前圖像的URI地址。
setInAnimation : 設置當前圖像的進入動畫。
setOutAnimation : 設置前一個圖像的退出動畫。
按照ImageSwitcher的上述方法,我們便能實現前後兩個圖像的切換動畫(如淡入淡出動畫)。可是還沒有實現左右滑動切換圖片的功能,既然Gallery上的小圖能夠左右滑動,那麼我們希望ImageSwitcher的大圖也能夠左右滑動,這時要借助於手勢事件來實現滑動切換功能。首先定義一個GestureDetector對象;然後調用ImageSwitcher的setOnTouchListener方法設置觸摸監聽器OnTouchListener,在該監聽器的onTouch方法中讓GestureDetector對象接管事件處理;最後重寫GestureDetector對象的手勢監聽器OnGestureListener,主要是在onFling方法中增加對左滑和右滑的處理邏輯判斷。
下面是Gallery與ImageSwitcher結合使用的效果截圖:
\
下面是Gallery與ImageSwitcher結合使用的代碼例子:
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.Gallery;
import android.widget.ImageSwitcher;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.ViewSwitcher.ViewFactory;

import com.example.exmcard.adapter.GalleryAdapter;
import com.example.exmcard.util.MetricsUtil;

@SuppressWarnings("deprecation")
public class SwitcherActivity extends Activity implements 
		OnTouchListener, OnItemClickListener {

	private ImageSwitcher is_switcher;
	private Gallery gl_switcher;

	// 圖片數組
	private int[] mImageRes = {
			R.drawable.scene1, R.drawable.scene2,
			R.drawable.scene3, R.drawable.scene4,
			R.drawable.scene5, R.drawable.scene6
			};
	private int dip_pad;

	private GestureDetector mGesture;
	private float mFlipGap = 20f;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_switcher);
		dip_pad = MetricsUtil.dip2px(this, 20);

		is_switcher = (ImageSwitcher) findViewById(R.id.is_switcher);
		is_switcher.setFactory(new ViewFactoryImpl());
		is_switcher.setImageResource(mImageRes[0]);
		mGesture = new GestureDetector(this, new GestureListener(this));
		is_switcher.setOnTouchListener(this);
		
		gl_switcher = (Gallery) findViewById(R.id.gl_switcher);
		gl_switcher.setPadding(dip_pad, dip_pad, dip_pad, dip_pad);
		gl_switcher.setSpacing(dip_pad);
		gl_switcher.setUnselectedAlpha(0.5f);
		gl_switcher.setAdapter(new GalleryAdapter(this, mImageRes));
		gl_switcher.setOnItemClickListener(this);
	}

	@Override
	public void onItemClick(AdapterView parent, View view, int position, long id) {
		is_switcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in));
		is_switcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));
		is_switcher.setImageResource(mImageRes[position]);
	}

	public class ViewFactoryImpl implements ViewFactory {

		@Override
		public View makeView() {
			ImageView iv = new ImageView(SwitcherActivity.this);
			iv.setBackgroundColor(0xFFFFFFFF);
			iv.setScaleType(ScaleType.FIT_XY);
			iv.setLayoutParams(new ImageSwitcher.LayoutParams(
					LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
			return iv;
		}

	}

	@SuppressLint("ClickableViewAccessibility")
	@Override
	public boolean onTouch(View v, MotionEvent event) {
		mGesture.onTouchEvent(event);
		return true;
	}

	private class GestureListener implements GestureDetector.OnGestureListener {
		private Context mContext;
		private GestureListener(Context context) {
			mContext = context;
		}

		@Override
		public final boolean onDown(MotionEvent event) {
			return true;
		}

		@Override
		public final boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
			if (e1.getX() - e2.getX() > mFlipGap) {
				is_switcher.setInAnimation(AnimationUtils.loadAnimation(mContext,
                        R.anim.push_left_in));
				is_switcher.setOutAnimation(AnimationUtils.loadAnimation(mContext,
                        R.anim.push_left_out));
				int next_pos = (int) (gl_switcher.getSelectedItemId()+1);
				if (next_pos >= mImageRes.length) {
					next_pos = 0;
				}
				is_switcher.setImageResource(mImageRes[next_pos]);
				gl_switcher.setSelection(next_pos);
				return true;
			}
			if (e1.getX() - e2.getX() < -mFlipGap) {
				is_switcher.setInAnimation(AnimationUtils.loadAnimation(mContext,
                        R.anim.push_right_in));
				is_switcher.setOutAnimation(AnimationUtils.loadAnimation(mContext,
                        R.anim.push_right_out));
				int pre_pos = (int) (gl_switcher.getSelectedItemId()-1);
				if (pre_pos < 0) {
					pre_pos = mImageRes.length-1;
				}
				is_switcher.setImageResource(mImageRes[pre_pos]);
				gl_switcher.setSelection(pre_pos);
				return true;
			}
			return false;
		}

		@Override
		public final void onLongPress(MotionEvent event) {
		}

		@Override
		public final boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
			return false;
		}

		@Override
		public final void onShowPress(MotionEvent event) {
		}

		@Override
		public boolean onSingleTapUp(MotionEvent event) {
			return false;
		}

	}

}

調色板Palette

Palette是Android在5.0中引入的調色板控件,它用於分析一個位圖對象的整體色調,最後給出樣品的色彩RGB值,這樣開發者就可以根據具體圖片動態設置整個頁面的背景色,從而實現統一的頁面風格。
Palette在android-support-v7-palette.jar中定義,同時需要最新的android-support-v4.jar支持。使用之前先在sdk的“sdk\extras\android\support\v7\palette\libs”目錄中找到jar包並在自己的工程中引用,如果在運行過程中報錯“Caused by: java.lang.NoClassDefFoundError: android.support.v4.graphics.ColorUtils”,則是因為Palette調用了v4包中新加的類ColorUtils,解決辦法是把最新的android-support-v4.jar導入到你的工程。
Palette的常用方法主要是兩個:
from : 從指定的Bitmap對象生成一個調色板建造者對象Palette.Builder。然後調用該Builder對象的generate方法即開始色調分析,generate方法的參數是個PaletteAsyncListener監聽器,監聽器的onGenerated方法就是完成分析之後的回調處理。
getVibrantSwatch : 獲得Palette對象的樣品。該方法在onGenerated中調用,返回值是Palette.Swatch樣品對象,調用該樣品對象的getRgb方法即可獲得樣品的色彩值。
下面是Gallery與Palette結合使用的效果截圖:
\
下面是Gallery與Palette結合使用的代碼例子:
import com.example.exmcard.adapter.GalleryAdapter;
import com.example.exmcard.util.MetricsUtil;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.graphics.Palette;
import android.support.v7.graphics.Palette.PaletteAsyncListener;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.AdapterView.OnItemClickListener;

@SuppressWarnings("deprecation")
public class PaletteActivity extends Activity implements 
		OnItemClickListener, PaletteAsyncListener {

	private ImageView iv_palette;
	private Gallery gl_palette;

	// 圖片數組
	private int[] mImageRes = {
			R.drawable.scene1, R.drawable.scene2,
			R.drawable.scene3, R.drawable.scene4,
			R.drawable.scene5, R.drawable.scene6
			};
	private int dip_pad;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_palette);
		dip_pad = MetricsUtil.dip2px(this, 20);

		iv_palette = (ImageView) findViewById(R.id.iv_palette);
		showBackground(mImageRes[0]);
		
		gl_palette = (Gallery) findViewById(R.id.gl_palette);
		gl_palette.setPadding(dip_pad, dip_pad, dip_pad, dip_pad);
		gl_palette.setSpacing(dip_pad);
		gl_palette.setUnselectedAlpha(0.5f);
		gl_palette.setAdapter(new GalleryAdapter(this, mImageRes));
		gl_palette.setOnItemClickListener(this);
	}
	
	private void showBackground(int res_id) {
		Drawable drawable = getResources().getDrawable(res_id);
		Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
		Palette.Builder builder = Palette.from(bitmap);
		builder.generate(this);
	}

	@Override
	public void onItemClick(AdapterView parent, View view, int position, long id) {
		showBackground(mImageRes[position]);
	}

	@Override
	public void onGenerated(Palette palette) {
		Palette.Swatch swatch = palette.getVibrantSwatch();
		if (swatch != null) {
			iv_palette.setBackgroundColor(swatch.getRgb());
		}
	}

}

卡片視圖CardView

CardView也是Android在5.0中新引入的卡片視圖控件,顧名思義它擁有一個卡片式的圓角邊框,邊框外緣有一圈陰影,邊框內緣有一圈空白。該控件的實現原理並不復雜,事實上早期便有許多人自己寫了類似卡片效果的控件,只不過後來Android順應民意推出了原生的卡片視圖。
使用CardView之前,要把“sdk\extras\android\support\v7\cardview”導入為一個庫工程,並引用到自己的工程中。如果在app運行的時候報錯:“Caused by: java.lang.NoClassDefFoundError: android.support.v7.cardview.R$styleable”,這是因為CardView源碼中引用了android.support.v7.cardview.R.styleable,而開發者自己的工程包名不是android.support.v7.cardview,所以就會找不到這個R$styleable。
解決步驟如下:
1、要引用整個android-support-v7-cardview工程,不能直接把android-support-v7-cardview.jar復制到自己工程的libs目錄。
2、把project.properties裡面的“target=android-19”改為“target=android-21”,注意庫工程和自己的工程都要改。
3、庫工程和自己的工程都Clean Project,然後再編譯運行。
CardView的常用屬性說明如下(因為引用的是庫工程,所以CardView節點的屬性要像自定義控件一樣對待,即先在根節點定義一個命名空間app指向res-auto,然後再使用app:屬性名稱來定義屬性值,不可直接使用android:屬性名稱):
cardBackgroundColor : 指定卡片的背景顏色。
cardCornerRadius : 指定卡片的圓角半徑。
cardElevation : 指定卡片內容距離陰影邊緣的間隔。
contentPadding : 指定卡片邊緣陰影的高程,即陰影的寬度。


CardView的常用方法說明如下:
setCardBackgroundColor : 設置卡片的背景顏色。
setRadius : 設置卡片的圓角半徑。
setContentPadding : 設置卡片內容距離陰影邊緣的間隔。
setCardElevation : 設置卡片邊緣陰影的高程,即陰影的寬度。
下面是使用CardView的效果截圖:
\
下面是使用CardView的代碼例子:
import com.example.exmcard.util.MetricsUtil;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.widget.CardView;

public class CardActivity extends Activity {
	private int dip_pad;
	private int dip_radius;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_card);
		dip_pad = MetricsUtil.dip2px(this, 20);
		dip_radius = MetricsUtil.dip2px(this, 10);
		
		CardView cv_one = (CardView) findViewById(R.id.cv_one);
		//cv_one.setCardBackgroundColor(Color.YELLOW);
		cv_one.setRadius(dip_radius);
		cv_one.setContentPadding(dip_pad, dip_pad, dip_pad, dip_pad);
		cv_one.setCardElevation(3f);

		CardView cv_two = (CardView) findViewById(R.id.cv_two);
		cv_two.setCardBackgroundColor(Color.GREEN);
		cv_two.setRadius(dip_radius);
		cv_two.setContentPadding(dip_pad, dip_pad, dip_pad, dip_pad);
		cv_two.setCardElevation(6f);
	}
	
}
下面是使用CardView的布局文件:


    

        

            
        
    

    

        

            

                

                
            
        
    

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved