在之前分析过这个ViewFlipper代码:
备注一:ViewFlipper
界面的最上面的mViewFlipper中包含了mGallery、mProgressBar、mFailureBar,刚开始以为最上面部分的显示是通过不同状态下设置View的visibility的VISIBLE,INVISIBLE, orGONE.来显示的,看完代码之后才知道是用的ViewFlipper这个空间实现的,代码显得更加清楚。
- <com.teleca.jamendo.util.FixedViewFlipper
- android:orientation="vertical"android:id="@+id/ViewFlipper"
- android:layout_width="fill_parent"android:layout_height="75dip"
- android:background="@drawable/gradient_dark_purple">
- <!--(0)Loading-->
- <LinearLayoutandroid:orientation="vertical"
- android:layout_width="fill_parent"android:layout_height="fill_parent"
- android:layout_marginLeft="15dip"android:gravity="left|center_vertical">
- <com.teleca.jamendo.widget.ProgressBar
- android:id="@+id/ProgressBar"android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- </com.teleca.jamendo.widget.ProgressBar>
- </LinearLayout>
- <!--(1)Gallery-->
- <LinearLayoutandroid:orientation="vertical"
- android:layout_width="fill_parent"android:layout_height="fill_parent"
- android:gravity="center">
- <Galleryandroid:id="@+id/Gallery"android:layout_width="fill_parent"
- android:layout_height="wrap_content"android:spacing="0px"/>
- </LinearLayout>
- <!--(2)Failure-->
- <LinearLayoutandroid:orientation="vertical"
- android:layout_width="fill_parent"android:layout_height="fill_parent"
- android:layout_marginLeft="15dip"android:gravity="left|center_vertical">
- <com.teleca.jamendo.widget.FailureBar
- android:id="@+id/FailureBar"android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- </com.teleca.jamendo.widget.FailureBar>
- </LinearLayout>
- </com.teleca.jamendo.util.FixedViewFlipper>
- privateclassNewsTaskextendsAsyncTask<Void,WSError,Album[]>{
- @Override
- publicvoidonPreExecute(){
- mViewFlipper.setDisplayedChild(0);
- mProgressBar.setText(R.string.loading_news);
- super.onPreExecute();
- }
- @Override
- publicAlbum[]doInBackground(Void...params){
- JamendoGet2Apiserver=newJamendoGet2ApiImpl();
- Album[]albums=null;
- try{
- albums=server.getPopularAlbumsWeek();
- }catch(JSONExceptione){
- e.printStackTrace();
- }catch(WSErrore){
- publishProgress(e);
- }
- returnalbums;
- }
- @Override
- publicvoidonPostExecute(Album[]albums){
- if(albums!=null&&albums.length>0){
- mViewFlipper.setDisplayedChild(1);
- ImageAdapteralbumsAdapter=newImageAdapter(HomeActivity.this);
- albumsAdapter.setList(albums);
- mGallery.setAdapter(albumsAdapter);
- mGallery.setOnItemClickListener(mGalleryListener);
- mGallery.setSelection(albums.length/2,true);//animatetocenter
- }else{
- mViewFlipper.setDisplayedChild(2);
- mFailureBar.setOnRetryListener(newOnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- newNewsTask().execute((Void)null);
- }
- });
- mFailureBar.setText(R.string.connection_fail);
- }
- super.onPostExecute(albums);
- }
- @Override
- protectedvoidonProgressUpdate(WSError...values){
- Toast.makeText(HomeActivity.this,values[0].getMessage(),Toast.LENGTH_LONG).show();
- super.onProgressUpdate(values);
- }
- }
SimpleViewAnimator
that will animate between two or more views that have been added to it. Only one child is shown at a time. If requested, can automatically flip between each child at a regular interval.
在com.teleca.jamendo.widget这个包中都是一些自定义的布局或者组件,这些布局和组件都是可以复用的。
ProgressBar
<!-- (0) Loading --> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginLeft="15dip" android:gravity="left|center_vertical"> <com.teleca.jamendo.widget.ProgressBar android:id="@+id/ProgressBar" android:layout_width="wrap_content" android:layout_height="wrap_content"> </com.teleca.jamendo.widget.ProgressBar> </LinearLayout>
这个是当程序加载的时候显示的
/** * Widget notifying user of ongoing action * * @author Lukasz Wisniewski */ public class ProgressBar extends LinearLayout { protected TextView mTextView; public ProgressBar(Context context, AttributeSet attrs) { super(context, attrs); init(); } public ProgressBar(Context context) { super(context); init(); } /** * Sharable code between constructors */ private void init(){ LayoutInflater.from(getContext()).inflate(R.layout.progress_bar, this); mTextView = (TextView)findViewById(R.id.ProgressTextView); } /** * Sets informative text * * @param resid */ public void setText(int resid){ mTextView.setText(resid); } }
progress_bar.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android"> <LinearLayout android:layout_height="wrap_content" android:minHeight="75dip" android:layout_width="fill_parent" android:orientation="horizontal" android:gravity="center_vertical" android:paddingLeft="13dip" android:paddingRight="13dip"> <ProgressBar android:id="@+id/ProgressBar" android:layout_width="48dip" android:layout_height="48dip"></ProgressBar> <LinearLayout android:layout_height="wrap_content" android:paddingLeft="13dip" android:orientation="vertical" android:layout_width="fill_parent"> <TextView android:id="@+id/ProgressTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/loading" android:textSize="20dip" android:textColor="#ffffff"></TextView> </LinearLayout> </LinearLayout> </merge>
我使用的时候只要mProgressBar.setText(R.string.loading_news);就可以设置他显示的文字信息RemoteImageView
/** * ImageView extended class allowing easy downloading * of remote images * * @author Lukasz Wisniewski */ public class RemoteImageView extends ImageView{ /** * Maximum number of unsuccesful tries of downloading an image */ private static int MAX_FAILURES = 3; public RemoteImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public RemoteImageView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public RemoteImageView(Context context) { super(context); init(); } /** * Sharable code between constructors */ private void init(){ } /** * Remote image location */ private String mUrl; /** * Currently successfully grabbed url */ private String mCurrentlyGrabbedUrl; /** * Remote image download failure counter */ private int mFailure; /** * Position of the image in the mListView */ private int mPosition; /** * ListView containg this image */ private ListView mListView; /** * Default image shown while loading or on url not found */ private Integer mDefaultImage; /** * Loads image from remote location * * @param url eg. http://random.com/abz.jpg */ public void setImageUrl(String url){ if(mListView == null && mCurrentlyGrabbedUrl != null && mCurrentlyGrabbedUrl.equals(url)){ // do nothing image is grabbed & loaded, we are golden return; } if(mUrl != null && mUrl.equals(url)){ mFailure++; if(mFailure > MAX_FAILURES){ Log.e(JamendoApplication.TAG, "Failed to download "+url+", falling back to default image"); loadDefaultImage(); return; } } else { mUrl = url; mFailure = 0; } ImageCache imageCache = JamendoApplication.getInstance().getImageCache(); if(imageCache.isCached(url)){ this.setImageBitmap(imageCache.get(url)); } else { try{ new DownloadTask().execute(url); } catch (RejectedExecutionException e) { // do nothing, just don't crash } } } /** * Sets default local image shown when remote one is unavailable * * @param resid */ public void setDefaultImage(Integer resid){ mDefaultImage = resid; } /** * Loads default image */ private void loadDefaultImage(){ if(mDefaultImage != null) setImageResource(mDefaultImage); } /** * Loads image from remote location in the ListView * * @param url eg. http://random.com/abz.jpg * @param position ListView position where the image is nested * @param listView ListView to which this image belongs */ public void setImageUrl(String url, int position, ListView listView){ mPosition = position; mListView = listView; setImageUrl(url); } /** * Asynchronous image download task * * @author Lukasz Wisniewski */ class DownloadTask extends AsyncTask<String, Void, String>{ private String mTaskUrl; @Override public void onPreExecute() { loadDefaultImage(); super.onPreExecute(); } @Override public String doInBackground(String... params) { mTaskUrl = params[0]; InputStream stream = null; URL imageUrl; Bitmap bmp = null; try { imageUrl = new URL(mTaskUrl); try { stream = imageUrl.openStream(); bmp = BitmapFactory.decodeStream(stream); try { if(bmp != null){ JamendoApplication.getInstance().getImageCache().put(mTaskUrl, bmp); Log.d(JamendoApplication.TAG, "Image cached "+mTaskUrl); } else { Log.w(JamendoApplication.TAG, "Failed to cache "+mTaskUrl); } } catch (NullPointerException e) { Log.w(JamendoApplication.TAG, "Failed to cache "+mTaskUrl); } } catch (IOException e) { Log.w(JamendoApplication.TAG, "Couldn't load bitmap from url: " + mTaskUrl); } finally { try { if(stream != null){ stream.close(); } } catch (IOException e) {} } } catch (MalformedURLException e) { e.printStackTrace(); } return mTaskUrl; } @Override public void onPostExecute(String url) { super.onPostExecute(url); // target url may change while loading if(!mTaskUrl.equals(mUrl)) return; Bitmap bmp = JamendoApplication.getInstance().getImageCache().get(url); if(bmp == null){ Log.w(JamendoApplication.TAG, "Trying again to download " + url); RemoteImageView.this.setImageUrl(url); } else { // if image belongs to a list update it only if it's visible if(mListView != null) if(mPosition < mListView.getFirstVisiblePosition() || mPosition > mListView.getLastVisiblePosition()) return; RemoteImageView.this.setImageBitmap(bmp); mCurrentlyGrabbedUrl = url; } } }; } 正如作者所说ImageView extended class allowing easy downloadingof remote images。这个很好的获取图片的封装类,使我想显示图片的时候不用关心怎么从网络获取图片以及怎么生成图片,我只要将图片的URL地址传进来就可以了,获取完图片调用父类ImageView的setImageBitmap就可以显示想要的图片了。