Advertisement bar effect implementation ---- ViewPager loads large images (LruCache) and regularly refreshes,

Source: Internet
Author: User

Advertisement bar effect implementation ---- ViewPager loads large images (LruCache) and regularly refreshes,

Let's take a look at the effect:



1. The advertising effect should be a widely used effect. The basic architecture is a ViewPager component. In earlier Android versions, you must manually import the v4 jar package before using it.


2. The Loading Method of ViewPager is not the same as that of listview. For listview, the sub-view is always used for reuse. However, when viewpager slides dynamically, it only keeps three pages in memory, that is, the current displayed page, the previous page and the last page, and other pages are destroyed and released.


3. If you do not process large images, one or two images may cause OOM and applications to crash. in earlier versions, before 2.3, A common practice is to use soft references and weak reference sets to process images loaded in the memory. However, for versions of Android3.0, android directly recycles soft-referenced objects rather than soft-referenced members, which makes this practice no longer applicable. However, the Android System also provides a better tool for processing image loading: LruCache. This class is very suitable for caching images. Its main algorithm principle is to store recently used objects with strong references in javashashmap, in addition, the minimum recently used objects are removed from the memory before the cache value reaches the preset value.


4. The problem raised during the loading of large images is that bitmapfactory is used to adjust the image size before loading. Here BitmapFactory is involved. options. inJustDecodeBounds = true; options. outHeight; and options. outWidth; get the width and height of the image, and then scale the Image Based on the width and height of the screen to achieve the compression effect.


5. Another small problem about ViewPager is that the data of viewpager cannot be refreshed directly by calling the adapter. notifydatasetchanged () method. The two solutions are as follows:

A. Override the getItemPosition method of the pageadapter and let it directly return POSITION_NONE. At this time, calling notifydatasetchanged can take effect.

B. After the data is updated, call a handler to send the corresponding message to manually refresh the local data. This method is recommended and can also be used for partial refresh of listview, which is more common.


6. Here we also implement a wireless circular slide on both sides. In fact, there are only six images, but we can slide to both sides wirelessly. In fact, the number of the two sides is integer. max_value/2,

The core idea is that the getCount method returns an integer. max) value and uses position % 6 for postion processing. For details, see the code.


Okay, let's get the code:

MainActivity:

Package com. example. advertisebardemo; import java. util. arrayList; import java. util. list; import java. util. concurrent. executors; import java. util. concurrent. scheduledExecutorService; import android. app. activity; import android. content. res. resources; import android. graphics. bitmap; import android. graphics. bitmapFactory; import android. graphics. bitmapFactory. options; import android. OS. asyncTask; import android. o S. bundle; import android. OS. handler; import android. OS. message; import android. support. v4.util. lruCache; import android. support. v4.view. pagerAdapter; import android. support. v4.view. viewPager; import android. support. v4.view. viewPager. onPageChangeListener; import android. text. format. formatter; import android. view. motionEvent; import android. view. view; import android. view. view. onTouchListener; import android. vi Ew. viewGroup; import android. view. windowManager; import android. widget. imageView; import android. widget. linearLayout; import android. widget. textView; public class MainActivity extends Activity {private ViewPager viewPager; private int [] ids = {R. drawable. a, R. drawable. b, R. drawable. c, R. drawable. d, R. drawable. e, R. drawable. f}; private List <ImageView> imageViews = new ArrayList <ImageView> (); private MyAda Pter adapter; private Options options; private int screenWidth; private int screenHeight; private LruCache <String, Bitmap> mMemoryCache; private WindowManager wm; private int wWidth; private int wHeight; /*** set a flag to determine whether to continue automatically sliding */private boolean isRunning = false; private int lastPointPosition; private boolean operationFlag; /*** thread pool Object */private ScheduledExecutorService pool; private Object [] objs; private S Tring [] descriptions = {"image description 1", "Image Description 2", "image description 3", "image description 4", "image description 5 ", "Image Description 6"}; private LinearLayout ll_points; private TextView TV _des; private Handler handler = new Handler () {@ Overridepublic void handleMessage (Message msg) {super. handleMessage (msg); switch (msg. what) {case 0: // adapter. notifyDataSetChanged (); // adapter is not required. notifyDataSetChanged (), and use the partial refresh method int tag = Integer. parseInt (String. valueOf (O Bject []) msg. obj) [0]); ImageView iv = (ImageView) viewPager. findViewWithTag (tag); iv. setImageBitmap (Bitmap) (Object []) msg. obj) [1]); break; case 1: viewPager. setCurrentItem (viewPager. getCurrentItem () + 1); // move a page later if (isRunning) {handler. sendEmptyMessageDelayed (1, 2000);} break; case 2: break; default: break ;}};@ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceStat E); setContentView (R. layout. activity_main); // initialize the imageviews set initImageViews (); // initialize viewinitViews () in the layout file; // initialize the window parameter initWindowParams (); // initialize lrucacheinitLruCache (); // The thread pool of the three threads = Executors. newScheduledThreadPool (3); // initialize a bitmapfactory option object options = new Options (); // initialize the initPointGroup (); policyadapter (); // set viewPager at the position of the first image near half of the Integer at the beginning. setCurrentItem (Integer. MAX_VALUE/2 + (Integer. MAX_V ALUE/2) % ids. length); // The Position of the automatic sliding flag is trueisRunning = true; // Add the sliding listener setViewPagerOnageChangeListener () to viewpager; // msg. what = 1, delay 2 seconds handler. sendEmptyMessageDelayed (1, 2000);} private void setViewPagerOnageChangeListener () {viewPager. setOnPageChangeListener (new OnPageChangeListener () {/*** callback method when the page is selected */@ Overridepublic void onPageSelected (int position) {ll_points.getChildAt (lastPointPosition % 6 ). s EtEnabled (false); ll_points.getChildAt (position % 6 ). setEnabled (true); lastPointPosition = position; // set the description text TV _des.setText (descriptions [position % 6]);} @ Overridepublic void onPageScrolled (int position, float positionOffset, int positionOffsetPixels) {// TODO Auto-generated method stub} @ Overridepublic void onPageScrollStateChanged (int state) {// TODO Auto-generated method stub});} private void ini TPointGroup () {LinearLayout. layoutParams layoutParams = new LinearLayout. layoutParams (15, 15); layoutParams. setMargins (15, 2, 15, 5); for (int I = 0; I <ids. length; I ++) {ImageView point = new ImageView (this); point. setBackgroundResource (R. drawable. point_bg); // set the location parameter point. setLayoutParams (layoutParams); if (I = 0) {point. setEnabled (true);} else {point. setEnabled (false);} ll_points.addView (point);} pr Ivate void initLruCache () {// lrucache transmits the cache value through the constructor, in kb, because the value is divided by 1204int maxMem = (int) (Runtime. getRuntime (). maxMemory ()/1024); // originally it was 1024. dividing it by 1024 here should be to prevent int type overflow int cacheSize = maxMem/4; System. out. println (Formatter. formatFileSize (this, cacheSize); mMemoryCache = new LruCache <String, Bitmap> (cacheSize) {@ Overrideprotected int sizeOf (String key, Bitmap bitmap) {// return super. sizeOf (key, value ); // Rewrite this method to measure the size of each image. By default, the number of images is returned. Return bitmap. getWidth () * bitmap. getHeight ()/1024; // The following statement requires API 12 // return bitmap. getByteCount ()/1024; // This is the same as the preceding one divided by 1024. }};} private void initWindowParams () {wm = (WindowManager) getSystemService (WINDOW_SERVICE ); wWidth = wm. getdefadisplay display (). getWidth (); wHeight = wm. getdefadisplay display (). getHeight ();} private void initViews () {ll_points = (LinearLayout) findViewById (R. id. ll_points); TV _des = (TextView) findViewById (R. id. TV _des); TV _des.setText (descriptions [0]); viewPager = (ViewPager) findViewById (R. id. viewPager); // parameter of viewpager size of the todo adaptive screen} private void initImageViews () {for (int I = 0; I <ids. length; I ++) {imageViews. add (new ImageView (this) ;}@ Overrideprotected void onDestroy () {// TODO Auto-generated method stubsuper. onDestroy (); isRunning = false; // android. OS. debug. stopMethodTraci Ng ();}/*** Add the bitmap of the corresponding key to the cache ** @ param key * @ param bitmap */public void addBitmapToMemoryCache (String key, Bitmap bitmap) {if (getBitmapFromMemCache (key) = null) {mMemoryCache. put (key, bitmap) ;}}/*** retrieves the bitmap object of the corresponding key from the cache ** @ param key * @ return */public Bitmap getBitmapFromMemCache (String key) {return mMemoryCache. get (key);}/*** method for setting apdater */private void policyadapter () {if (adapt Er = null) {adapter = new MyAdapter (); viewPager. setAdapter (adapter);} else {/** found that the following sentence cannot refresh data, unless the return value of the getItemPosition method is set to POSITION_NONE * // adapter. notifyDataSetChanged () ;}} public void loadBitmap (int resId, ImageView imageView) {final String imageKey = String. valueOf (resId); final Bitmap bitmap = getBitmapFromMemCache (imageKey); if (bitmap! = Null) {imageView. setImageBitmap (bitmap);} else {// imageView. setImageResource (R. drawable. ic_launcher); // default // here the AsyncTask method BitmapWorkerTask task = new bitmapworkertask(;;;task.exe cute (resId); // The following method uses the thread pool. Both methods are available, the thread pool may be better for network loading. // pool. submit (new MyRunnable (resId) ;}} class MyRunnable implements Runnable {private int id; public MyRunnable () {super ();} public MyRunnable (int id) {super (); this. id = Id ;}@ Overridepublic void run () {final Bitmap bitmap = decodeSampledBitmapFromResource (getResources (), id, wWidth, wHeight); System. out. println ("wWidth =" + wWidth); System. out. println ("wHeight =" + wHeight); addBitmapToMemoryCache (String. valueOf (id), bitmap); Message msg = Message. obtain (); msg. what = 0; objs = new Object [] {id, bitmap}; msg. obj = objs; handler. sendMessage (msg) ;}} class BitmapWorkerTask e Xtends AsyncTask <Integer, Void, Bitmap> {// load the image in the background. @ Overrideprotected Bitmap doInBackground (Integer... params) {final Bitmap bitmap = decodeSampledBitmapFromResource (getResources (), params [0], wWidth, wHeight); System. out. println ("wWidth =" + wWidth); System. out. println ("wHeight =" + wHeight); addBitmapToMemoryCache (String. valueOf (params [0]), bitmap); Message msg = Message. obtain (); msg. what = 0; objs = new Object [] {params [0], bitmap}; msg. obj = objs; han Dler. sendMessage (msg); return bitmap;} public static Bitmap decodeSampledBitmapFromResource (Resources res, int resId, int reqWidth, int reqHeight) {// set inJustDecodeBounds to true for the first parsing, to obtain the final BitmapFactory image size. options options = new BitmapFactory. options (); options. inJustDecodeBounds = true; BitmapFactory. decodeResource (res, resId, options); // call the method defined above to calculate the inSampleSize value options. inSampleSize = calculateInS AmpleSize (options, reqWidth, reqHeight); System. out. println ("inSampleSize =" + options. inSampleSize); // use the obtained inSampleSize value to parse the image options again. inJustDecodeBounds = false; return BitmapFactory. decodeResource (res, resId, options);} public static int calculateInSampleSize (BitmapFactory. options options, int reqWidth, int reqHeight) {// the height and width of the source image final int height = options. outHeight; final int width = options. outWid Th; System. out. println ("height =" + height); System. out. println ("width =" + width); int inSampleSize = 1; if (height> reqHeight | width> reqWidth) {// calculate the ratio of actual width to target width. final int heightRatio = Math. round (float) height/(float) reqHeight); final int widthRatio = Math. round (float) width/(float) reqWidth); // select the ratio of the width and the smallest ratio of the high school as the value of inSampleSize, this ensures that the width and height of the final image must be greater than or equal to the width and height of the target. // InSampleSize = heightRatio <widthRatio? HeightRatio: // widthRatio; // here we select the width method, so the ratio of the width is inSampleSize = widthRatio;} return inSampleSize ;} private class MyAdapter extends PagerAdapter {@ Overridepublic int getCount () {// return ids. length; return Integer. MAX_VALUE ;}@ Overridepublic boolean isViewFromObject (View view, Object object) {// TODO Auto-generated method stubreturn view = object ;}@ Overridepublic Object instantiateItem (ViewGroup container, int position) {ImageView imageView = imageViews. get (position % 6); container. addView (imageView); loadBitmap (ids [position % 6], imageView); // hook the id with imageview by using the setTag method to imageView. setTag (ids [position % 6]); return imageView;} @ Overridepublic void destroyItem (ViewGroup container, int position, Object object) {container. removeView (View) object); object = null;} // ** // after a position_none is returned, Dynamic Refresh of viewpager is implemented, however, some problems are also raised: // * // @ Override // public int getItemPosition (Object object Object) {// TODO Auto-generated method stub // return super. getItemPosition (object); // return POSITION_NONE ;//}}}



Layout file:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="${relativePackage}.${activityClass}" >    <android.support.v4.view.ViewPager        android:id="@+id/viewPager"        android:layout_width="fill_parent"        android:layout_height="202.5dp"        android:layout_gravity="top" />    <LinearLayout        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_alignBottom="@id/viewPager"        android:background="#66ffffff"        android:gravity="bottom"        android:orientation="vertical" >        <TextView            android:id="@+id/tv_des"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:gravity="center_horizontal"            android:textSize="15sp" />        <LinearLayout            android:id="@+id/ll_points"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:gravity="center_horizontal"            android:orientation="horizontal" >        </LinearLayout>    </LinearLayout></RelativeLayout>



Point_bg.xml:

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <item android:drawable="@drawable/point_normal" android:state_enabled="false"></item>    <item android:drawable="@drawable/point_focused" android:state_enabled="true"></item></selector>



Point_normal.xml:

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"    android:shape="oval" >    <size        android:height="5dp"        android:width="5dp" />    <solid android:color="#55eeeeee" /></shape>



Point_focused.xml:

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"    android:shape="oval" >    <size        android:height="5dp"        android:width="5dp" />    <solid android:color="#ffffffff" /></shape>





Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.