Screen slides are transitions between one entire screen to another and are common with UIs like setup wizards or slideshows. This Android tutorial shows how to create image slideshow with ViewPager (provided as part of Android support library). ViewPager can animate screen slides automatically.
Here’s what a screen slide looks like – transition from one screen to the next:
Project Description:
In this Android Image Slideshow tutorial we will be doing the following,
- Create an image slideshow along with image description using ViewPager and display circle indicator to show the current position in the slideshow.
- Enclose ViewPager and circle indicator in a layout and provide a border.
- Retrieve and parse JSON (product information) from remote server and store it as list of products.
- Handle ViewPager item clicks to display product details in another fragment (ProductDetailFragment)
- Proper back navigation of fragments on back key pressed.
- Handle fragment orientation changes and retain the state of the fragment.
We will also be using the following library projects,
- Universal Image Loader for Android for asynchronous image loading.
- ViewPagerIndicator library to bring circle indicator with ViewPager.
Prerequisites
- Place the Universal Image Loader JAR file in your libs folder and add it to project’s “Build Path”.
Create JSON File
Create a new JSON file and name it as
products.json
and copy-paste the following content. Place this file in a remote server, for example Apache server’s “www” folder or
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
{
"status"
:
true
,
"data"
:
{
"products"
:
[
{
"id"
:
"434"
,
"name"
:
"Pattern - Fractal Wallpaper"
,
"image_url"
:
"http://images5.alphacoders.com/350/350374.jpg"
}
,
{
"id"
:
"431"
,
"name"
:
"Mickey Mouse"
,
"image_url"
:
"http://www.iconsdb.com/icons/download/icon-sets/sketchy-pink/mickey-mouse-20-512.png"
}
,
{
"id"
:
"424"
,
"name"
:
"Pattern - Wallpaper"
,
"image_url"
:
"http://images7.alphacoders.com/421/421423.jpg"
}
,
{
"id"
:
"426"
,
"name"
:
"Batman"
,
"image_url"
:
"http://www.iconsdb.com/icons/download/icon-sets/sketchy-pink/batman-6-512.png"
}
,
{
"id"
:
"419"
,
"name"
:
"Pattern - Music"
,
"image_url"
:
"http://images3.alphacoders.com/169/169085.jpg"
}
]
}
}
|
Android Project
Create a new Android project and name it as AndroidImageSlideShow .
Resources
colors.xml
Create a new file res/values/colors.xml and copy paste the following content.
|
1
2
3
4
5
6
7
8
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
resources
>
<
color
name
=
"holo_blue_dark"
>
#ff0099cc</color>
<
color
name
=
"view_divider_color"
>
#BABABA</color>
<
color
name
=
"view_divider_color_2"
>
#DADADA</color>
<
/
resources
>
|
strings.xml
Open res/values/strings.xml and edit to have the content as shown below.
|
1
2
3
4
5
6
7
8
9
10
11
12
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
resources
>
<
string
name
=
"app_name"
>
AndroidImageSlideShow
<
/
string
>
<
string
name
=
"action_settings"
>
Settings
<
/
string
>
<
string
name
=
"product_name"
>
Product
Name
<
/
string
>
<
string
name
=
"txt_image_slider"
>
Image
Slideshow
<
/
string
>
<
string
name
=
"no_internet_connection"
>
No
Internet
Connection
<
/
string
>
<
string
name
=
"time_out"
>
Time
Out
<
/
string
>
<
string
name
=
"error_occured"
>
Error
Occurred
<
/
string
>
<
/
resources
>
|
indicator_tags.xml
Create a new file res/values/indicator_tags.xml and copy the following content. The attributes defined here are used by circle page indicator. You can use this file to change the circle indicator fill color, stroke color, stroke width, circle radius and any other related styles.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
resources
>
<
bool
name
=
"default_circle_indicator_centered"
>
true
<
/
bool
>
<
color
name
=
"default_circle_indicator_fill_color"
>
#FFFF0000</color>
<
color
name
=
"default_circle_indicator_page_color"
>
#00000000</color>
<
integer
name
=
"default_circle_indicator_orientation"
>
0
<
/
integer
>
<
dimen
name
=
"default_circle_indicator_radius"
>
4dp
<
/
dimen
>
<
bool
name
=
"default_circle_indicator_snap"
>
false
<
/
bool
>
<
color
name
=
"default_circle_indicator_stroke_color"
>
#FFDDDDDD</color>
<
dimen
name
=
"default_circle_indicator_stroke_width"
>
1dp
<
/
dimen
>
<
declare
-
styleable
name
=
"ViewPagerIndicator"
>
<
!
--
Style
of
the
circle
indicator
.
--
>
<
attr
name
=
"vpiCirclePageIndicatorStyle"
format
=
"reference"
/
>
<
!
--
Style
of
the
icon
indicator
's views. -->
<attr name="vpiIconPageIndicatorStyle" format="reference" />
<!-- Style of the line indicator. -->
<attr name="vpiLinePageIndicatorStyle" format="reference" />
<!-- Style of the title indicator. -->
<attr name="vpiTitlePageIndicatorStyle" format="reference" />
<!-- Style of the tab indicator'
s
tabs
.
--
>
<
attr
name
=
"vpiTabPageIndicatorStyle"
format
=
"reference"
/
>
<
!
--
Style
of
the
underline
indicator
.
--
>
<
attr
name
=
"vpiUnderlinePageIndicatorStyle"
format
=
"reference"
/
>
<
/
declare
-
styleable
>
<
attr
name
=
"centered"
format
=
"boolean"
/
>
<
attr
name
=
"selectedColor"
format
=
"color"
/
>
<
attr
name
=
"strokeWidth"
format
=
"dimension"
/
>
<
attr
name
=
"unselectedColor"
format
=
"color"
/
>
<
declare
-
styleable
name
=
"CirclePageIndicator"
>
<
!
--
Whether
or
not
the
indicators
should
be
centered
.
--
>
<
attr
name
=
"centered"
/
>
<
!
--
Color
of
the
filled
circle
that
represents
the
current
page
.
--
>
<
attr
name
=
"fillColor"
format
=
"color"
/
>
<
!
--
Color
of
the
filled
circles
that
represents
pages
.
--
>
<
attr
name
=
"pageColor"
format
=
"color"
/
>
<
!
--
Orientation
of
the
indicator
.
--
>
<
attr
name
=
"android:orientation"
/
>
<
!
--
Radius
of
the
circles
.
This
is
also
the
spacing
between
circles
.
--
>
<
attr
name
=
"radius"
format
=
"dimension"
/
>
<
!
--
Whether
or
not
the
selected
indicator
snaps
to
the
circles
.
--
>
<
attr
name
=
"snap"
format
=
"boolean"
/
>
<
!
--
Color
of
the
open
circles
.
--
>
<
attr
name
=
"strokeColor"
format
=
"color"
/
>
<
!
--
Width
of
the
stroke
used
to
draw
the
circles
.
--
>
<
attr
name
=
"strokeWidth"
/
>
<
!
--
View
background
--
>
<
attr
name
=
"android:background"
/
>
<
/
declare
-
styleable
>
<
declare
-
styleable
name
=
"LinePageIndicator"
>
<
!
--
Whether
or
not
the
indicators
should
be
centered
.
--
>
<
attr
name
=
"centered"
/
>
<
!
--
Color
of
the
unselected
lines
that
represent
the
pages
.
--
>
<
attr
name
=
"unselectedColor"
/
>
<
!
--
Color
of
the
selected
line
that
represents
the
current
page
.
--
>
<
attr
name
=
"selectedColor"
/
>
<
!
--
Width
of
each
indicator
line
.
--
>
<
attr
name
=
"lineWidth"
format
=
"dimension"
/
>
<
!
--
Width
of
each
indicator
line
'
s
stroke
.
--
>
<
attr
name
=
"strokeWidth"
/
>
<
!
--
Width
of
the
gap
between
each
indicator
line
.
--
>
<
attr
name
=
"gapWidth"
format
=
"dimension"
/
>
<
!
--
View
background
--
>
<
attr
name
=
"android:background"
/
>
<
/
declare
-
styleable
>
<
declare
-
styleable
name
=
"TitlePageIndicator"
>
<
!
--
Screen
edge
padding
.
--
>
<
attr
name
=
"clipPadding"
format
=
"dimension"
/
>
<
!
--
Color
of
the
footer
line
and
indicator
.
--
>
<
attr
name
=
"footerColor"
format
=
"color"
/
>
<
!
--
Height
of
the
footer
line
.
--
>
<
attr
name
=
"footerLineHeight"
format
=
"dimension"
/
>
<
!
--
Style
of
the
indicator
.
Default
is
triangle
.
--
>
<
attr
name
=
"footerIndicatorStyle"
>
<
enum
name
=
"none"
value
=
"0"
/
>
<
enum
name
=
"triangle"
value
=
"1"
/
>
<
enum
name
=
"underline"
value
=
"2"
/
>
<
/
attr
>
<
!
--
Height
of
the
indicator
above
the
footer
line
.
--
>
<
attr
name
=
"footerIndicatorHeight"
format
=
"dimension"
/
>
<
!
--
Left
and
right
padding
of
the
underline
indicator
.
--
>
<
attr
name
=
"footerIndicatorUnderlinePadding"
format
=
"dimension"
/
>
<
!
--
Padding
between
the
bottom
of
the
title
and
the
footer
.
--
>
<
attr
name
=
"footerPadding"
format
=
"dimension"
/
>
<
!
--
Position
of
the
line
.
--
>
<
attr
name
=
"linePosition"
>
<
enum
name
=
"bottom"
value
=
"0"
/
>
<
enum
name
=
"top"
value
=
"1"
/
>
<
/
attr
>
<
!
--
Color
of
the
selected
title
.
--
>
<
attr
name
=
"selectedColor"
/
>
<
!
--
Whether
or
not
the
selected
item
is
displayed
as
bold
.
--
>
<
attr
name
=
"selectedBold"
format
=
"boolean"
/
>
<
!
--
Color
of
regular
titles
.
--
>
<
attr
name
=
"android:textColor"
/
>
<
!
--
Size
of
title
text
.
--
>
<
attr
name
=
"android:textSize"
/
>
<
!
--
Padding
between
titles
when
bumping
into
each
other
.
--
>
<
attr
name
=
"titlePadding"
format
=
"dimension"
/
>
<
!
--
Padding
between
titles
and
the
top
of
the
View
.
--
>
<
attr
name
=
"topPadding"
format
=
"dimension"
/
>
<
!
--
View
background
--
>
<
attr
name
=
"android:background"
/
>
<
/
declare
-
styleable
>
<
declare
-
styleable
name
=
"UnderlinePageIndicator"
>
<
!
--
Whether
or
not
the
selected
indicator
fades
.
--
>
<
attr
name
=
"fades"
format
=
"boolean"
/
>
<
!
--
Length
of
the
delay
to
fade
the
indicator
.
--
>
<
attr
name
=
"fadeDelay"
format
=
"integer"
/
>
<
!
--
Length
of
the
indicator
fade
to
transparent
.
--
>
<
attr
name
=
"fadeLength"
format
=
"integer"
/
>
<
!
--
Color
of
the
selected
line
that
represents
the
current
page
.
--
>
<
attr
name
=
"selectedColor"
/
>
<
!
--
View
background
--
>
<
attr
name
=
"android:background"
/
>
<
/
declare
-
styleable
>
<
/
resources
>
|
img_border.xml
Create a new file res/drawable/img_border.xml and copy the following content. This brings a border to ViewPager and circle page indicator layout.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
shape
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
android
:
dither
=
"true"
android
:
shape
=
"rectangle"
>
<
solid
android
:
color
=
"#FFFFFF"
/
>
<
stroke
android
:
width
=
"1dp"
android
:
color
=
"#AAAAAA"
/
>
<
padding
android
:
bottom
=
"1dp"
android
:
left
=
"1dp"
android
:
right
=
"1dp"
android
:
top
=
"1dp"
/
>
<
/
shape
>
|
Layout files
activity_main.xml
This is the main layout file which uses a Framelayout to hold fragments. Open res/layout/activity_main.xml and edit to have the content as shown below.
|
1
2
3
4
5
6
7
8
9
10
11
12
|
<
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
=
".MainActivity"
>
<
FrameLayout
android
:
id
=
"@+id/content_frame"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"match_parent"
/
>
<
/
RelativeLayout
>
|
fragment_home.xml
This layout file is used by HomeFragment to display image slide show using ViewPager. Here it encloses ViewPager and circle page indicator in a single layout by displaying circle page indicator over ViewPager.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
<
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"
android
:
padding
=
"10dp"
tools
:
context
=
".MainActivity"
>
<
RelativeLayout
android
:
id
=
"@+id/img_slide_header_layout"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"wrap_content"
>
<
TextView
android
:
id
=
"@+id/txt_image_slider"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"wrap_content"
android
:
layout_alignParentLeft
=
"true"
android
:
padding
=
"4dp"
android
:
paddingLeft
=
"20dp"
android
:
text
=
"@string/txt_image_slider"
android
:
textColor
=
"@color/holo_blue_dark"
android
:
textSize
=
"16sp"
android
:
textStyle
=
"bold"
/
>
<
View
android
:
id
=
"@+id/div1"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"2dp"
android
:
layout_below
=
"@+id/txt_image_slider"
android
:
layout_marginBottom
=
"7dp"
android
:
layout_marginTop
=
"4dp"
android
:
background
=
"@color/holo_blue_dark"
/
>
<
/
RelativeLayout
>
<
RelativeLayout
android
:
id
=
"@+id/img_slideshow_layout"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"wrap_content"
android
:
layout_below
=
"@+id/img_slide_header_layout"
android
:
layout_marginTop
=
"10dp"
android
:
background
=
"@drawable/img_border"
>
<
android
.
support
.
v4
.
view
.
ViewPager
android
:
id
=
"@+id/view_pager"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"150dp"
/
>
<
TextView
android
:
id
=
"@+id/img_name"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"wrap_content"
android
:
layout_below
=
"@+id/indicator"
android
:
background
=
"#88343434"
android
:
ellipsize
=
"end"
android
:
paddingBottom
=
"2dp"
android
:
paddingLeft
=
"5dp"
android
:
paddingRight
=
"2dp"
android
:
paddingTop
=
"2dp"
android
:
singleLine
=
"true"
android
:
textColor
=
"#ededed"
/
>
<
com
.
androidopentutorials
.
imageslideshow
.
utils
.
CirclePageIndicator
android
:
id
=
"@+id/indicator"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"wrap_content"
android
:
layout_below
=
"@+id/view_pager"
android
:
padding
=
"10dip"
/
>
<
/
RelativeLayout
>
<
View
android
:
id
=
"@+id/div_a"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"1dp"
android
:
layout_below
=
"@+id/img_slideshow_layout"
android
:
background
=
"@color/view_divider_color"
/
>
<
View
android
:
id
=
"@+id/div_b"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"1dp"
android
:
layout_below
=
"@+id/div_a"
android
:
background
=
"@color/sliding_list_divider_color"
/
>
<
/
RelativeLayout
>
|
vp_image.xml
This layout file is for the content of a fragment to be used by ViewPager. The file contains an image view.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
RelativeLayout
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
xmlns
:
tools
=
"http://schemas.android.com/tools"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"fill_parent"
android
:
padding
=
"10dp"
>
<
ImageView
android
:
id
=
"@+id/image_display"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"fill_parent"
android
:
contentDescription
=
"@string/txt_image_slider"
/
>
<
/
RelativeLayout
>
|
fragmet_pdt_detail.xml
This layout file is used by ProductDetailFragment to display product details when a page (fragment) in ViewPager is clicked.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
RelativeLayout
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
android
:
id
=
"@+id/pdt_detail_root_layout"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"fill_parent"
android
:
background
=
"#FFFFFF"
>
<
RelativeLayout
android
:
id
=
"@+id/header_layout"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"wrap_content"
android
:
padding
=
"5dp"
>
<
RelativeLayout
android
:
id
=
"@+id/header_title_layout"
android
:
layout_width
=
"90dp"
android
:
layout_height
=
"wrap_content"
>
<
ImageView
android
:
id
=
"@+id/product_detail_img"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"100dp"
android
:
contentDescription
=
"@string/app_name"
android
:
scaleType
=
"fitCenter"
android
:
src
=
"@drawable/ic_launcher"
/
>
<
/
RelativeLayout
>
<
TextView
android
:
id
=
"@+id/product_id_text"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"wrap_content"
android
:
layout_marginLeft
=
"10dp"
android
:
layout_marginTop
=
"10dp"
android
:
paddingTop
=
"10dp"
android
:
layout_toRightOf
=
"@+id/header_title_layout"
android
:
textSize
=
"15sp"
android
:
textStyle
=
"bold"
/
>
<
/
RelativeLayout
>
<
View
android
:
id
=
"@+id/div_line1"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"1dp"
android
:
layout_below
=
"@+id/header_layout"
android
:
background
=
"@color/view_divider_color"
/
>
<
View
android
:
id
=
"@+id/div_line2"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"1dp"
android
:
layout_below
=
"@+id/div_line1"
android
:
background
=
"@color/sliding_list_divider_color"
/
>
<
ScrollView
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"fill_parent"
android
:
layout_below
=
"@+id/div_line1"
android
:
background
=
"#EDEDED"
android
:
padding
=
"10dp"
android
:
scrollbarStyle
=
"outsideOverlay"
>
<
LinearLayout
android
:
id
=
"@+id/rlayout_detail"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"wrap_content"
android
:
orientation
=
"vertical"
>
<
RelativeLayout
android
:
id
=
"@+id/pdt_name_layout"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"wrap_content"
android
:
layout_marginTop
=
"10dp"
android
:
background
=
"@android:color/white"
android
:
paddingBottom
=
"10dp"
>
<
TextView
android
:
id
=
"@+id/pdt_name_title"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"wrap_content"
android
:
paddingBottom
=
"4dp"
android
:
paddingLeft
=
"12dp"
android
:
paddingRight
=
"4dp"
android
:
paddingTop
=
"4dp"
android
:
text
=
"@string/product_name"
android
:
textColor
=
"@color/holo_blue_dark"
android
:
textSize
=
"15sp"
android
:
textStyle
=
"bold"
/
>
<
View
android
:
id
=
"@+id/div_a"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"2dp"
android
:
layout_below
=
"@+id/pdt_name_title"
android
:
layout_marginLeft
=
"10dp"
android
:
layout_marginRight
=
"10dp"
android
:
background
=
"@color/view_divider_color"
/
>
<
TextView
android
:
id
=
"@+id/pdt_name"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"wrap_content"
android
:
layout_alignLeft
=
"@+id/div_a"
android
:
layout_below
=
"@+id/div_a"
android
:
layout_marginLeft
=
"5dp"
android
:
layout_marginTop
=
"7dp"
/
>
<
/
RelativeLayout
>
<
/
LinearLayout
>
<
/
ScrollView
>
<
!
--
<
ProgressBar
android
:
id
=
"@+id/progressBar"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"wrap_content"
android
:
layout_centerInParent
=
"true"
android
:
visibility
=
"gone"
/
>
--
>
<
/
RelativeLayout
>
|
Sources
TagName
In src folder, create a new class TagName in the package com.androidopentutorials.imageslideshow.utils . This class defines tag and key names defined in JSON.
|
1
2
3
4
5
6
7
8
9
10
11
|
package
com
.
androidopentutorials
.
imageslideshow
.
utils
;
public
class
TagName
{
public
static
final
String
TAG_STATUS
=
"status"
;
public
static
final
String
TAG_DATA
=
"data"
;
public
static
final
String
TAG_PRODUCTS
=
"products"
;
public
static
final
String
KEY_NAME
=
"name"
;
public
static
final
String
KEY_IMAGE_URL
=
"image_url"
;
public
static
final
String
KEY_ID
=
"id"
;
}
|
CheckNetworkConnection
In src folder, create a new class CheckNetworkConnection in the package com.androidopentutorials.imageslideshow.utils .
Before our app attempts to connect to the network, it should check to see whether a network connection is available using getActiveNetworkInfo() and isConnected(). Remember, the device may be out of range of a network, or the user may have disabled both Wi-Fi and mobile data access.
We use this class to check whether the device has internet connection before sending request to receive remote JSON.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package
com
.
androidopentutorials
.
imageslideshow
.
utils
;
import
android
.
content
.
Context
;
import
android
.
net
.
ConnectivityManager
;
import
android
.
net
.
NetworkInfo
;
public
class
CheckNetworkConnection
{
public
static
boolean
isConnectionAvailable
(
Context
context
)
{
ConnectivityManager
connectivityManager
=
(
ConnectivityManager
)
context
.
getSystemService
(
Context
.
CONNECTIVITY_SERVICE
)
;
if
(
connectivityManager
!=
null
)
{
NetworkInfo
netInfo
=
connectivityManager
.
getActiveNetworkInfo
(
)
;
if
(
netInfo
!=
null
&&
netInfo
.
isConnected
(
)
&&
netInfo
.
isConnectedOrConnecting
(
)
&&
netInfo
.
isAvailable
(
)
)
{
return
true
;
}
}
return
false
;
}
}
|
PageIndicator
In src folder, create a new interface PageIndicator in the package com.androidopentutorials.imageslideshow.utils . This is a class from Android ViewPagerIndicator library which is used to draw a circle indicator over the ViewPager. This interface is responsible for showing an visual indicator indicating the currently visible view.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
/*
* Copyright (C) 2011 Patrik Akerfeldt
* 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.
*/
package
com
.
androidopentutorials
.
imageslideshow
.
utils
;
import
android
.
support
.
v4
.
view
.
ViewPager
;
/**
* A PageIndicator is responsible to show an visual indicator on the total views
* number and the current visible view.
*/
public
interface
PageIndicator
extends
ViewPager
.
OnPageChangeListener
{
/**
* Bind the indicator to a ViewPager.
*
* @param view
*/
void
setViewPager
(
ViewPager
view
)
;
/**
* Bind the indicator to a ViewPager.
*
* @param view
* @param initialPosition
*/
void
setViewPager
(
ViewPager
view
,
int
initialPosition
)
;
/**
* <p>Set the current page of both the ViewPager and indicator.</p>
*
* <p>This <strong>must</strong> be used if you need to set the page before
* the views are drawn on screen (e.g., default start page).</p>
*
* @param item
*/
void
setCurrentItem
(
int
item
)
;
/**
* Set a page change listener which will receive forwarded events.
*
* @param listener
*/
void
setOnPageChangeListener
(
ViewPager
.
OnPageChangeListener
listener
)
;
/**
* Notify the indicator that the fragment list has changed.
*/
void
notifyDataSetChanged
(
)
;
}
|
CirclePageIndicator
In src folder, create a new class CirclePageIndicator in the package com.androidopentutorials.imageslideshow.utils . This is also a class from Android ViewPagerIndicator library which implements the above interface.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
|
/*
* Copyright (C) 2011 Patrik Akerfeldt
* 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.
*/
package
com
.
androidopentutorials
.
imageslideshow
.
utils
;
import
static
android
.
graphics
.
Paint
.
ANTI_ALIAS_FLAG
;
import
static
android
.
widget
.
LinearLayout
.
HORIZONTAL
;
import
static
android
.
widget
.
LinearLayout
.
VERTICAL
;
import
android
.
content
.
Context
;
import
android
.
content
.
res
.
Resources
;
import
android
.
content
.
res
.
TypedArray
;
import
android
.
graphics
.
Canvas
;
import
android
.
graphics
.
Paint
;
import
android
.
graphics
.
Paint
.
Style
;
import
android
.
graphics
.
drawable
.
Drawable
;
import
android
.
os
.
Parcel
;
import
android
.
os
.
Parcelable
;
import
android
.
support
.
v4
.
view
.
MotionEventCompat
;
import
android
.
support
.
v4
.
view
.
ViewConfigurationCompat
;
import
android
.
support
.
v4
.
view
.
ViewPager
;
import
android
.
util
.
AttributeSet
;
import
android
.
view
.
MotionEvent
;
import
android
.
view
.
View
;
import
android
.
view
.
ViewConfiguration
;
import
com
.
androidopentutorials
.
imageslideshow
.
R
;
/**
* Draws circles (one for each view). The current view position is filled and
* others are only stroked.
*/
public
class
CirclePageIndicator
extends
View
implements
PageIndicator
{
private
static
final
int
INVALID_POINTER
=
-
1
;
private
float
mRadius
;
private
final
Paint
mPaintPageFill
=
new
Paint
(
ANTI_ALIAS_FLAG
)
;
private
final
Paint
mPaintStroke
=
new
Paint
(
ANTI_ALIAS_FLAG
)
;
private
final
Paint
mPaintFill
=
new
Paint
(
ANTI_ALIAS_FLAG
)
;
private
ViewPager
mViewPager
;
private
ViewPager
.
OnPageChangeListener
mListener
;
private
int
mCurrentPage
;
private
int
mSnapPage
;
private
float
mPageOffset
;
private
int
mScrollState
;
private
int
mOrientation
;
private
boolean
mCentered
;
private
boolean
mSnap
;
private
int
mTouchSlop
;
private
float
mLastMotionX
=
-
1
;
private
int
mActivePointerId
=
INVALID_POINTER
;
private
boolean
mIsDragging
;
public
CirclePageIndicator
(
Context
context
)
{
this
(
context
,
null
)
;
}
public
CirclePageIndicator
(
Context
context
,
AttributeSet
attrs
)
{
this
(
context
,
attrs
,
R
.
attr
.
vpiCirclePageIndicatorStyle
)
;
}
public
CirclePageIndicator
(
Context
context
,
AttributeSet
attrs
,
int
defStyle
)
{
super
(
context
,
attrs
,
defStyle
)
;
if
(
isInEditMode
(
)
)
return
;
//Load defaults from resources
final
Resources
res
=
getResources
(
)
;
final
int
defaultPageColor
=
res
.
getColor
(
R
.
color
.
default_circle_indicator_page_color
)
;
//default_circle_indicator_fill_color
final
int
defaultFillColor
=
res
.
getColor
(
R
.
color
.
holo_blue_dark
)
;
final
int
defaultOrientation
=
res
.
getInteger
(
R
.
integer
.
default_circle_indicator_orientation
)
;
final
int
defaultStrokeColor
=
res
.
getColor
(
R
.
color
.
default_circle_indicator_stroke_color
)
;
final
float
defaultStrokeWidth
=
res
.
getDimension
(
R
.
dimen
.
default_circle_indicator_stroke_width
)
;
final
float
defaultRadius
=
res
.
getDimension
(
R
.
dimen
.
default_circle_indicator_radius
)
;
final
boolean
defaultCentered
=
res
.
getBoolean
(
R
.
bool
.
default_circle_indicator_centered
)
;
final
boolean
defaultSnap
=
res
.
getBoolean
(
R
.
bool
.
default_circle_indicator_snap
)
;
//Retrieve styles attributes
TypedArray
a
=
context
.
obtainStyledAttributes
(
attrs
,
R
.
styleable
.
CirclePageIndicator
,
defStyle
,
0
)
;
mCentered
=
a
.
getBoolean
(
R
.
styleable
.
CirclePageIndicator_centered
,
defaultCentered
)
;
mOrientation
=
a
.
getInt
(
R
.
styleable
.
CirclePageIndicator_android_orientation
,
defaultOrientation
)
;
mPaintPageFill
.
setStyle
(
Style
.
FILL
)
;
mPaintPageFill
.
setColor
(
a
.
getColor
(
R
.
styleable
.
CirclePageIndicator_pageColor
,
defaultPageColor
)
)
;
mPaintStroke
.
setStyle
(
Style
.
STROKE
)
;
mPaintStroke
.
setColor
(
a
.
getColor
(
R
.
styleable
.
CirclePageIndicator_strokeColor
,
defaultStrokeColor
)
)
;
mPaintStroke
.
setStrokeWidth
(
a
.
getDimension
(
R
.
styleable
.
CirclePageIndicator_strokeWidth
,
defaultStrokeWidth
)
)
;
mPaintFill
.
setStyle
(
Style
.
FILL
)
;
mPaintFill
.
setColor
(
a
.
getColor
(
R
.
styleable
.
CirclePageIndicator_fillColor
,
defaultFillColor
)
)
;
mRadius
=
a
.
getDimension
(
R
.
styleable
.
CirclePageIndicator_radius
,
defaultRadius
)
;
mSnap
=
a
.
getBoolean
(
R
.
styleable
.
CirclePageIndicator_snap
,
defaultSnap
)
;
Drawable
background
=
a
.
getDrawable
(
R
.
styleable
.
CirclePageIndicator_android_background
)
;
if
(
background
!=
null
)
{
setBackgroundDrawable
(
background
)
;
}
a
.
recycle
(
)
;
final
ViewConfiguration
configuration
=
ViewConfiguration
.
get
(
context
)
;
mTouchSlop
=
ViewConfigurationCompat
.
getScaledPagingTouchSlop
(
configuration
)
;
}
public
void
setCentered
(
boolean
centered
)
{
mCentered
=
centered
;
invalidate
(
)
;
}
public
boolean
isCentered
(
)
{
return
mCentered
;
}
public
void
setPageColor
(
int
pageColor
)
{
mPaintPageFill
.
setColor
(
pageColor
)
;
invalidate
(
)
;
}
public
int
getPageColor
(
)
{
return
mPaintPageFill
.
getColor
(
)
;
}
public
void
setFillColor
(
int
fillColor
)
{
mPaintFill
.
setColor
(
fillColor
)
;
invalidate
(
)
;
}
public
int
getFillColor
(
)
{
return
mPaintFill
.
getColor
(
)
;
}
public
void
setOrientation
(
int
orientation
)
{
switch
(
orientation
)
{
case
HORIZONTAL
:
case
VERTICAL
:
mOrientation
=
orientation
;
requestLayout
(
)
;
break
;
default
:
throw
new
IllegalArgumentException
(
"Orientation must be either HORIZONTAL or VERTICAL."
)
;
}
}
public
int
getOrientation
(
)
{
return
mOrientation
;
}
public
void
setStrokeColor
(
int
strokeColor
)
{
mPaintStroke
.
setColor
(
strokeColor
)
;
invalidate
(
)
;
}
public
int
getStrokeColor
(
)
{
return
mPaintStroke
.
getColor
(
)
;
}
public
void
setStrokeWidth
(
float
strokeWidth
)
{
mPaintStroke
.
setStrokeWidth
(
strokeWidth
)
;
invalidate
(
)
;
}
public
float
getStrokeWidth
(
)
{
return
mPaintStroke
.
getStrokeWidth
(
)
;
}
public
void
setRadius
(
float
radius
)
{
mRadius
=
radius
;
invalidate
(
)
;
}
public
float
getRadius
(
)
{
return
mRadius
;
}
public
void
setSnap
(
boolean
snap
)
{
mSnap
=
snap
;
invalidate
(
)
;
}
public
boolean
isSnap
(
)
{
return
mSnap
;
}
@
Override
protected
void
onDraw
(
Canvas
canvas
)
{
super
.
onDraw
(
canvas
)
;
if
(
mViewPager
==
null
)
{
return
;
}
final
int
count
=
mViewPager
.
getAdapter
(
)
.
getCount
(
)
;
if
(
count
==
0
)
{
return
;
}
if
(
mCurrentPage
>=
count
)
{
setCurrentItem
(
count
-
1
)
;
return
;
}
int
longSize
;
int
longPaddingBefore
;
int
longPaddingAfter
;
int
shortPaddingBefore
;
if
(
mOrientation
==
HORIZONTAL
)
{
longSize
=
getWidth
(
)
;
longPaddingBefore
=
getPaddingLeft
(
)
;
longPaddingAfter
=
getPaddingRight
(
)
;
shortPaddingBefore
=
getPaddingTop
(
)
;
}
else
{
longSize
=
getHeight
(
)
;
longPaddingBefore
=
getPaddingTop
(
)
;
longPaddingAfter
=
getPaddingBottom
(
)
;
shortPaddingBefore
=
getPaddingLeft
(
)
;
}
final
float
threeRadius
=
mRadius *
3
;
final
float
shortOffset
=
shortPaddingBefore
+
mRadius
;
float
longOffset
=
longPaddingBefore
+
mRadius
;
if
(
mCentered
)
{
longOffset
+=
(
(
longSize
-
longPaddingBefore
-
longPaddingAfter
)
/
2.0f
)
-
(
(
count *
threeRadius
)
/
2.0f
)
;
}
float
dX
;
float
dY
;
float
pageFillRadius
=
mRadius
;
if
(
mPaintStroke
.
getStrokeWidth
(
)
>
0
)
{
pageFillRadius
-=
mPaintStroke
.
getStrokeWidth
(
)
/
2.0f
;
}
//Draw stroked circles
for
(
int
iLoop
=
0
;
iLoop
<
count
;
iLoop
++
)
{
float
drawLong
=
longOffset
+
(
iLoop *
threeRadius
)
;
if
(
mOrientation
==
HORIZONTAL
)
{
dX
=
drawLong
;
dY
=
shortOffset
;
}
else
{
dX
=
shortOffset
;
dY
=
drawLong
;
}
// Only paint fill if not completely transparent
if
(
mPaintPageFill
.
getAlpha
(
)
>
0
)
{
canvas
.
drawCircle
(
dX
,
dY
,
pageFillRadius
,
mPaintPageFill
)
;
}
// Only paint stroke if a stroke width was non-zero
if
(
pageFillRadius
!=
mRadius
)
{
canvas
.
drawCircle
(
dX
,
dY
,
mRadius
,
mPaintStroke
)
;
}
}
//Draw the filled circle according to the current scroll
float
cx
=
(
mSnap
?
mSnapPage
:
mCurrentPage
)
*
threeRadius
;
if
(
!
mSnap
)
{
cx
+=
mPageOffset *
threeRadius
;
}
if
(
mOrientation
==
HORIZONTAL
)
{
dX
=
longOffset
+
cx
;
dY
=
shortOffset
;
}
else
{
dX
=
shortOffset
;
dY
=
longOffset
+
cx
;
}
canvas
.
drawCircle
(
dX
,
dY
,
mRadius
,
mPaintFill
)
;
}
public
boolean
onTouchEvent
(
android
.
view
.
MotionEvent
ev
)
{
if
(
super
.
onTouchEvent
(
ev
)
)
{
return
true
;
}
if
(
(
mViewPager
==
null
)
||
(
mViewPager
.
getAdapter
(
)
.
getCount
(
)
==
0
)
)
{
return
false
;
}
final
int
action
=
ev
.
getAction
(
)
&
MotionEventCompat
.
ACTION_MASK
;
switch
(
action
)
{
case
MotionEvent
.
ACTION_DOWN
:
mActivePointerId
=
MotionEventCompat
.
getPointerId
(
ev
,
0
)
;
mLastMotionX
=
ev
.
getX
(
)
;
break
;
case
MotionEvent
.
ACTION_MOVE
:
{
final
int
activePointerIndex
=
MotionEventCompat
.
findPointerIndex
(
ev
,
mActivePointerId
)
;
final
float
x
=
MotionEventCompat
.
getX
(
ev
,
activePointerIndex
)
;
final
float
deltaX
=
x
-
mLastMotionX
;
if
(
!
mIsDragging
)
{
if
(
Math
.
abs
(
deltaX
)
>
mTouchSlop
)
{
mIsDragging
=
true
;
}
}
if
(
mIsDragging
)
{
mLastMotionX
=
x
;
if
(
mViewPager
.
isFakeDragging
(
)
||
mViewPager
.
beginFakeDrag
(
)
)
{
mViewPager
.
fakeDragBy
(
deltaX
)
;
}
}
break
;
}
case
MotionEvent
.
ACTION_CANCEL
:
case
MotionEvent
.
ACTION_UP
:
if
(
!
mIsDragging
)
{
final
int
count
=
mViewPager
.
getAdapter
(
)
.
getCount
(
)
;
final
int
width
=
getWidth
(
)
;
final
float
halfWidth
=
width
/
2f
;
final
float
sixthWidth
=
width
/
6f
;
if
(
(
mCurrentPage
>
0
)
&&
(
ev
.
getX
(
)
<
halfWidth
-
sixthWidth
)
)
{
if
(
action
!=
MotionEvent
.
ACTION_CANCEL
)
{
mViewPager
.
setCurrentItem
(
mCurrentPage
-
1
)
;
}
return
true
;
}
else
if
(
(
mCurrentPage
<
count
-
1
)
&&
(
ev
.
getX
(
)
>
halfWidth
+
sixthWidth
)
)
{
if
(
action
!=
MotionEvent
.
ACTION_CANCEL
)
{
mViewPager
.
setCurrentItem
(
mCurrentPage
+
1
)
;
}
return
true
;
}
}
mIsDragging
=
false
;
mActivePointerId
=
INVALID_POINTER
;
if
(
mViewPager
.
isFakeDragging
(
)
)
mViewPager
.
endFakeDrag
(
)
;
break
;
case
MotionEventCompat
.
ACTION_POINTER_DOWN
:
{
final
int
index
=
MotionEventCompat
.
getActionIndex
(
ev
)
;
mLastMotionX
=
MotionEventCompat
.
getX
(
ev
,
index
)
;
mActivePointerId
=
MotionEventCompat
.
getPointerId
(
ev
,
index
)
;
break
;
}
case
MotionEventCompat
.
ACTION_POINTER_UP
:
final
int
pointerIndex
=
MotionEventCompat
.
getActionIndex
(
ev
)
;
final
int
pointerId
=
MotionEventCompat
.
getPointerId
(
ev
,
pointerIndex
)
;
if
(
pointerId
==
mActivePointerId
)
{
final
int
newPointerIndex
=
pointerIndex
==
0
?
1
:
0
;
mActivePointerId
=
MotionEventCompat
.
getPointerId
(
ev
,
newPointerIndex
)
;
}
mLastMotionX
=
MotionEventCompat
.
getX
(
ev
,
MotionEventCompat
.
findPointerIndex
(
ev
,
mActivePointerId
)
)
;
break
;
}
return
true
;
}
@
Override
public
void
setViewPager
(
ViewPager
view
)
{
if
(
mViewPager
==
view
)
{
return
;
}
if
(
mViewPager
!=
null
)
{
mViewPager
.
setOnPageChangeListener
(
null
)
;
}
if
(
view
.
getAdapter
(
)
==
null
)
{
throw
new
IllegalStateException
(
"ViewPager does not have adapter instance."
)
;
}
mViewPager
=
view
;
mViewPager
.
setOnPageChangeListener
(
this
)
;
invalidate
(
)
;
}
@
Override
public
void
setViewPager
(
ViewPager
view
,
int
initialPosition
)
{
setViewPager
(
view
)
;
setCurrentItem
(
initialPosition
)
;
}
@
Override
public
void
setCurrentItem
(
int
item
)
{
if
(
mViewPager
==
null
)
{
throw
new
IllegalStateException
(
"ViewPager has not been bound."
)
;
}
mViewPager
.
setCurrentItem
(
item
)
;
mCurrentPage
=
item
;
invalidate
(
)
;
}
@
Override
public
void
notifyDataSetChanged
(
)
{
invalidate
(
)
;
}
@
Override
public
void
onPageScrollStateChanged
(
int
state
)
{
mScrollState
=
state
;
if
(
mListener
!=
null
)
{
mListener
.
onPageScrollStateChanged
(
state
)
;
}
}
@
Override
public
void
onPageScrolled
(
int
position
,
float
positionOffset
,
int
positionOffsetPixels
)
{
mCurrentPage
=
position
;
mPageOffset
=
positionOffset
;
invalidate
(
)
;
if
(
mListener
!=
null
)
{
mListener
.
onPageScrolled
(
position
,
positionOffset
,
positionOffsetPixels
)
;
}
}
@
Override
public
void
onPageSelected
(
int
position
)
{
if
(
mSnap
||
mScrollState
==
ViewPager
.
SCROLL_STATE_IDLE
)
{
mCurrentPage
=
position
;
mSnapPage
=
position
;
invalidate
(
)
;
}
if
(
mListener
!=
null
)
{
mListener
.
onPageSelected
(
position
)
;
}
}
@
Override
public
void
setOnPageChangeListener
(
ViewPager
.
OnPageChangeListener
listener
)
{
mListener
=
listener
;
}
/*
* (non-Javadoc)
*
* @see android.view.View#onMeasure(int, int)
*/
@
Override
protected
void
onMeasure
(
int
widthMeasureSpec
,
int
heightMeasureSpec
)
{
if
(
mOrientation
==
HORIZONTAL
)
{
setMeasuredDimension
(
measureLong
(
widthMeasureSpec
)
,
measureShort
(
heightMeasureSpec
)
)
;
}
else
{
setMeasuredDimension
(
measureShort
(
widthMeasureSpec
)
,
measureLong
(
heightMeasureSpec
)
)
;
}
}
/**
* Determines the width of this view
*
* @param measureSpec
* A measureSpec packed into an int
* @return The width of the view, honoring constraints from measureSpec
*/
private
int
measureLong
(
int
measureSpec
)
{
int
result
;
int
specMode
=
MeasureSpec
.
getMode
(
measureSpec
)
;
int
specSize
=
MeasureSpec
.
getSize
(
measureSpec
)
;
if
(
(
specMode
==
MeasureSpec
.
EXACTLY
)
||
(
mViewPager
==
null
)
)
{
//We were told how big to be
result
=
specSize
;
}
else
{
//Calculate the width according the views count
final
int
count
=
mViewPager
.
getAdapter
(
)
.
getCount
(
)
;
result
=
(
int
)
(
getPaddingLeft
(
)
+
getPaddingRight
(
)
+
(
count *
2
*
mRadius
)
+
(
count
-
1
)
*
mRadius
+
1
)
;
//Respect AT_MOST value if that was what is called for by measureSpec
if
(
specMode
==
MeasureSpec
.
AT_MOST
)
{
result
=
Math
.
min
(
result
,
specSize
)
;
}
}
return
result
;
}
/**
* Determines the height of this view
*
* @param measureSpec
* A measureSpec packed into an int
* @return The height of the view, honoring constraints from measureSpec
*/
private
int
measureShort
(
int
measureSpec
)
{
int
result
;
int
specMode
=
MeasureSpec
.
getMode
(
measureSpec
)
;
int
specSize
=
MeasureSpec
.
getSize
(
measureSpec
)
;
if
(
specMode
==
MeasureSpec
.
EXACTLY
)
{
//We were told how big to be
result
=
specSize
;
}
else
{
//Measure the height
result
=
(
int
)
(
2
*
mRadius
+
getPaddingTop
(
)
+
getPaddingBottom
(
)
+
1
)
;
//Respect AT_MOST value if that was what is called for by measureSpec
if
(
specMode
==
MeasureSpec
.
AT_MOST
)
{
result
=
Math
.
min
(
result
,
specSize
)
;
}
}
return
result
;
}
@
Override
public
void
onRestoreInstanceState
(
Parcelable
state
)
{
SavedState
savedState
=
(
SavedState
)
state
;
super
.
onRestoreInstanceState
(
savedState
.
getSuperState
(
)
)
;
mCurrentPage
=
savedState
.
currentPage
;
mSnapPage
=
savedState
.
currentPage
;
requestLayout
(
)
;
}
@
Override
public
Parcelable
onSaveInstanceState
(
)
{
Parcelable
superState
=
super
.
onSaveInstanceState
(
)
;
SavedState
savedState
=
new
SavedState
(
superState
)
;
savedState
.
currentPage
=
mCurrentPage
;
return
savedState
;
}
static
class
SavedState
extends
BaseSavedState
{
int
currentPage
;
public
SavedState
(
Parcelable
superState
)
{
super
(
superState
)
;
}
private
SavedState
(
Parcel
in
)
{
super
(
in
)
;
currentPage
=
in
.
readInt
(
)
;
}
@
Override
public
void
writeToParcel
(
Parcel
dest
,
int
flags
)
{
super
.
writeToParcel
(
dest
,
flags
)
;
dest
.
writeInt
(
currentPage
)
;
}
@
SuppressWarnings
(
"UnusedDeclaration"
)
public
static
final
Parcelable
.
Creator
<
SavedState
>
CREATOR
=
new
Parcelable
.
Creator
<
SavedState
>
(
)
{
@
Override
public
SavedState
createFromParcel
(
Parcel
in
)
{
return
new
SavedState
(
in
)
;
}
@
Override
public
SavedState
[
]
newArray
(
int
size
)
{
return
new
SavedState
[
size
]
;
}
}
;
}
}
|
FileUtils
In src folder, create a new class FileUtils in the package com.androidopentutorials.imageslideshow.utils . This class has utility methods to close Reader, Writer, InputStream and OutputStream which is used by JSONParser class.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
package
com
.
androidopentutorials
.
imageslideshow
.
utils
;
import
java
.
io
.
IOException
;
import
java
.
io
.
InputStream
;
import
java
.
io
.
OutputStream
;
import
java
.
io
.
Reader
;
import
java
.
io
.
Writer
;
public
class
FileUtils
{
public
static
void
close
(
Reader
reader
)
{
if
(
reader
!=
null
)
try
{
reader
.
close
(
)
;
}
catch
(
IOException
e
)
{
}
}
public
static
void
close
(
Writer
writer
)
{
if
(
writer
!=
null
)
try
{
writer
.
close
(
)
;
}
catch
(
IOException
e
)
{
}
}
public
static
void
close
(
InputStream
inputStream
)
{
if
(
inputStream
!=
null
)
try
{
inputStream
.
close
(
)
;
}
catch
(
IOException
e
)
{
}
}
public
static
void
close
(
OutputStream
outputStream
)
{
if
(
outputStream
!=
null
)
try
{
outputStream
.
close
(
)
;
}
catch
(
IOException
e
)
{
}
}
}
|
GetJSONObject
In src folder, create a new class GetJSONObject in the package com.androidopentutorials.imageslideshow.json . For the given URL, it gets JSONObject. It checks for Android version, if it is greater than FROYO then it uses HttpURLConnection else uses HttpClient. For more information on this refer Android Http Clients .
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package
com
.
androidopentutorials
.
imageslideshow
.
json
;
import
java
.
io
.
IOException
;
import
org
.
json
.
JSONException
;
import
org
.
json
.
JSONObject
;
import
android
.
os
.
Build
;
public
class
GetJSONObject
{
public
static
JSONObject
getJSONObject
(
String
url
)
throws
IOException
,
JSONException
{
JSONParser
jsonParser
=
new
JSONParser
(
)
;
JSONObject
jsonObject
=
null
;
// Use HttpURLConnection
if
(
Build
.
VERSION
.
SDK_INT
>
Build
.
VERSION_CODES
.
FROYO
)
{
jsonObject
=
jsonParser
.
getJSONHttpURLConnection
(
url
)
;
}
else
{
// use HttpClient
jsonObject
=
jsonParser
.
getJSONHttpClient
(
url
)
;
}
return
jsonObject
;
}
}
|
JSONParser
In src folder, create a new class JSONParser in the package com.androidopentutorials.imageslideshow.json . This class opens a connection to the remote json url, creates a reader object, retrieves the json string and returns a JSONObject.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
package
com
.
androidopentutorials
.
imageslideshow
.
json
;
import
java
.
io
.
BufferedReader
;
import
java
.
io
.
IOException
;
import
java
.
io
.
InputStream
;
import
java
.
io
.
InputStreamReader
;
import
java
.
net
.
HttpURLConnection
;
import
java
.
net
.
URL
;
import
java
.
net
.
URLConnection
;
import
org
.
apache
.
http
.
HttpEntity
;
import
org
.
apache
.
http
.
HttpResponse
;
import
org
.
apache
.
http
.
client
.
ClientProtocolException
;
import
org
.
apache
.
http
.
client
.
methods
.
HttpGet
;
import
org
.
apache
.
http
.
impl
.
client
.
DefaultHttpClient
;
import
org
.
apache
.
http
.
params
.
HttpConnectionParams
;
import
org
.
apache
.
http
.
params
.
HttpParams
;
import
org
.
json
.
JSONException
;
import
org
.
json
.
JSONObject
;
import
android
.
util
.
Log
;
import
com
.
androidopentutorials
.
imageslideshow
.
utils
.
FileUtils
;
public
class
JSONParser
{
static
String
json
=
""
;
private
HttpURLConnection
httpConnection
;
InputStream
inputStream
=
null
;
BufferedReader
reader
=
null
;
public
JSONParser
(
)
{
}
private
void
openHttpUrlConnection
(
String
urlString
)
throws
IOException
{
Log
.
d
(
"urlstring in parser"
,
urlString
+
""
)
;
URL
url
=
new
URL
(
urlString
)
;
URLConnection
connection
=
url
.
openConnection
(
)
;
httpConnection
=
(
HttpURLConnection
)
connection
;
httpConnection
.
setConnectTimeout
(
30000
)
;
httpConnection
.
setRequestMethod
(
"GET"
)
;
httpConnection
.
connect
(
)
;
}
private
void
openHttpClient
(
String
urlString
)
throws
IOException
{
DefaultHttpClient
httpClient
=
new
DefaultHttpClient
(
)
;
HttpParams
httpParams
=
httpClient
.
getParams
(
)
;
HttpConnectionParams
.
setConnectionTimeout
(
httpParams
,
30000
)
;
HttpGet
httpGet
=
new
HttpGet
(
urlString
)
;
HttpResponse
httpResponse
=
httpClient
.
execute
(
httpGet
)
;
HttpEntity
httpEntity
=
httpResponse
.
getEntity
(
)
;
inputStream
=
httpEntity
.
getContent
(
)
;
reader
=
new
BufferedReader
(
new
InputStreamReader
(
inputStream
,
"UTF-8"
)
,
8
)
;
}
// using HttpClient for <= Froyo
public
JSONObject
getJSONHttpClient
(
String
url
)
throws
ClientProtocolException
,
IOException
,
JSONException
{
JSONObject
jsonObject
=
null
;
try
{
openHttpClient
(
url
)
;
StringBuilder
sb
=
new
StringBuilder
(
)
;
String
line
=
null
;
while
(
(
line
=
reader
.
readLine
(
)
)
!=
null
)
{
sb
.
append
(
line
+
"\n"
)
;
}
json
=
sb
.
toString
(
)
;
Log
.
d
(
"json"
,
json
)
;
jsonObject
=
new
JSONObject
(
json
)
;
}
finally
{
FileUtils
.
close
(
inputStream
)
;
FileUtils
.
close
(
reader
)
;
}
return
jsonObject
;
}
// using HttpURLConnection for > Froyo
public
JSONObject
getJSONHttpURLConnection
(
String
urlString
)
throws
IOException
,
JSONException
{
BufferedReader
reader
=
null
;
StringBuffer
output
=
new
StringBuffer
(
""
)
;
InputStream
stream
=
null
;
JSONObject
jsonObject
=
null
;
try
{
openHttpUrlConnection
(
urlString
)
;
if
(
httpConnection
.
getResponseCode
(
)
==
HttpURLConnection
.
HTTP_OK
)
{
stream
=
httpConnection
.
getInputStream
(
)
;
reader
=
new
BufferedReader
(
new
InputStreamReader
(
stream
,
"UTF-8"
)
,
8
)
;
String
line
=
""
;
while
(
(
line
=
reader
.
readLine
(
)
)
!=
null
)
output
.
append
(
line
+
"\n"
)
;
json
=
output
.
toString
(
)
;
jsonObject
=
new
JSONObject
(
json
)
;
}
}
finally
{
FileUtils
.
close
(
stream
)
;
FileUtils
.
close
(
reader
)
;
}
return
jsonObject
;
}
}
|
JsonReader
In src folder, create a new class JsonReader in the package com.androidopentutorials.imageslideshow.json . This class has an utility method which takes JSONObject as parameter, parses it and returns a list of products.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package
com
.
androidopentutorials
.
imageslideshow
.
json
;
import
java
.
util
.
ArrayList
;
import
java
.
util
.
List
;
import
org
.
json
.
JSONArray
;
import
org
.
json
.
JSONException
;
import
org
.
json
.
JSONObject
;
import
com
.
androidopentutorials
.
imageslideshow
.
bean
.
Product
;
import
com
.
androidopentutorials
.
imageslideshow
.
utils
.
TagName
;
public
class
JsonReader
{
public
static
List
<
Product
>
getHome
(
JSONObject
jsonObject
)
throws
JSONException
{
List
<
Product
>
products
=
new
ArrayList
<
Product
>
(
)
;
JSONArray
jsonArray
=
jsonObject
.
getJSONArray
(
TagName
.
TAG_PRODUCTS
)
;
Product
product
;
for
(
int
i
=
0
;
i
<
jsonArray
.
length
(
)
;
i
++
)
{
product
=
new
Product
(
)
;
JSONObject
productObj
=
jsonArray
.
getJSONObject
(
i
)
;
product
.
setId
(
productObj
.
getInt
(
TagName
.
KEY_ID
)
)
;
product
.
setName
(
productObj
.
getString
(
TagName
.
KEY_NAME
)
)
;
product
.
setImageUrl
(
productObj
.
getString
(
TagName
.
KEY_IMAGE_URL
)
)
;
products
.
add
(
product
)
;
}
return
products
;
}
}
|
Product
In src folder, create a new class Product in the package com.androidopentutorials.imageslideshow.bean . This is a bean class which represents a single product.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
package
com
.
androidopentutorials
.
imageslideshow
.
bean
;
import
android
.
os
.
Parcel
;
import
android
.
os
.
Parcelable
;
public
class
Product
implements
Parcelable
{
private
int
id
;
private
String
name
;
private
String
imageUrl
;
public
Product
(
)
{
super
(
)
;
}
private
Product
(
Parcel
in
)
{
super
(
)
;
this
.
id
=
in
.
readInt
(
)
;
this
.
name
=
in
.
readString
(
)
;
this
.
imageUrl
=
in
.
readString
(
)
;
}
@
Override
public
int
describeContents
(
)
{
return
0
;
}
@
Override
public
void
writeToParcel
(
Parcel
parcel
,
int
flags
)
{
parcel
.
writeInt
(
getId
(
)
)
;
parcel
.
writeString
(
getName
(
)
)
;
parcel
.
writeString
(
getImageUrl
(
)
)
;
}
public
static
final
Parcelable
.
Creator
<
Product
>
CREATOR
=
new
Parcelable
.
Creator
<
Product
>
(
)
{
public
Product
createFromParcel
(
Parcel
in
)
{
return
new
Product
(
in
)
;
}
public
Product
[
]
newArray
(
int
size
)
{
return
new
Product
[
size
]
;
}
}
;
public
int
getId
(
)
{
return
id
;
}
public
void
setId
(
int
id
)
{
this
.
id
=
id
;
}
public
String
getName
(
)
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
String
getImageUrl
(
)
{
return
imageUrl
;
}
public
void
setImageUrl
(
String
imageUrl
)
{
this
.
imageUrl
=
imageUrl
;
}
public
static
Parcelable
.
Creator
<
Product
>
getCreator
(
)
{
return
CREATOR
;
}
@
Override
public
int
hashCode
(
)
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime *
result
+
id
;
return
result
;
}
@
Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
getClass
(
)
!=
obj
.
getClass
(
)
)
return
false
;
Product
other
=
(
Product
)
obj
;
if
(
id
!=
other
.
id
)
return
false
;
return
true
;
}
@
Override
public
String
toString
(
)
{
return
"Product [id="
+
id
+
", name="
+
name
+
", imageUrl="
+
imageUrl
+
"]"
;
}
}
|
ImageSlideAdapter
In src folder, create a new class ImageSlideAdapter in the package com.androidopentutorials.imageslideshow.adapter .
- This class is an implementation of PagerAdapter to populate pages inside a ViewPager.
-
When you implement a PagerAdapter, you must override the following methods at minimum:
- instantiateItem(ViewGroup, int)
- destroyItem(ViewGroup, int, Object)
- getCount()
- isViewFromObject(View, Object)
- When the ImageView is clicked, it starts a FragmentTransaction and replaces the content frame with ProductDetailFragment.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
package
com
.
androidopentutorials
.
imageslideshow
.
adapter
;
import
java
.
util
.
Collections
;
import
java
.
util
.
LinkedList
;
import
java
.
util
.
List
;
import
android
.
app
.
Activity
;
import
android
.
graphics
.
Bitmap
;
import
android
.
os
.
Bundle
;
import
android
.
support
.
v4
.
app
.
Fragment
;
import
android
.
support
.
v4
.
app
.
FragmentActivity
;
import
android
.
support
.
v4
.
app
.
FragmentTransaction
;
import
android
.
support
.
v4
.
view
.
PagerAdapter
;
import
android
.
util
.
Log
;
import
android
.
view
.
LayoutInflater
;
import
android
.
view
.
View
;
import
android
.
view
.
View
.
OnClickListener
;
import
android
.
view
.
ViewGroup
;
import
android
.
widget
.
ImageView
;
import
com
.
androidopentutorials
.
imageslideshow
.
R
;
import
com
.
androidopentutorials
.
imageslideshow
.
bean
.
Product
;
import
com
.
androidopentutorials
.
imageslideshow
.
fragment
.
HomeFragment
;
import
com
.
androidopentutorials
.
imageslideshow
.
fragment
.
ProductDetailFragment
;
import
com
.
nostra13
.
universalimageloader
.
core
.
DisplayImageOptions
;
import
com
.
nostra13
.
universalimageloader
.
core
.
ImageLoader
;
import
com
.
nostra13
.
universalimageloader
.
core
.
assist
.
ImageLoadingListener
;
import
com
.
nostra13
.
universalimageloader
.
core
.
assist
.
SimpleImageLoadingListener
;
import
com
.
nostra13
.
universalimageloader
.
core
.
display
.
FadeInBitmapDisplayer
;
public
class
ImageSlideAdapter
extends
PagerAdapter
{
ImageLoader
imageLoader
=
ImageLoader
.
getInstance
(
)
;
DisplayImageOptions
options
;
private
ImageLoadingListener
imageListener
;
FragmentActivity
activity
;
List
<
Product
>
products
;
HomeFragment
homeFragment
;
public
ImageSlideAdapter
(
FragmentActivity
activity
,
List
<
Product
>
products
,
HomeFragment
homeFragment
)
{
this
.
activity
=
activity
;
this
.
homeFragment
=
homeFragment
;
this
.
products
=
products
;
options
=
new
DisplayImageOptions
.
Builder
(
)
.
showImageOnFail
(
R
.
drawable
.
ic_error
)
.
showStubImage
(
R
.
drawable
.
ic_launcher
)
.
showImageForEmptyUri
(
R
.
drawable
.
ic_empty
)
.
cacheInMemory
(
)
.
cacheOnDisc
(
)
.
build
(
)
;
imageListener
=
new
ImageDisplayListener
(
)
;
}
@
Override
public
int
getCount
(
)
{
return
products
.
size
(
)
;
}
@
Override
public
View
instantiateItem
(
ViewGroup
container
,
final
int
position
)
{
LayoutInflater
inflater
=
(
LayoutInflater
)
activity
.
getSystemService
(
Activity
.
LAYOUT_INFLATER_SERVICE
)
;
View
view
=
inflater
.
inflate
(
R
.
layout
.
vp_image
,
container
,
false
)
;
ImageView
mImageView
=
(
ImageView
)
view
.
findViewById
(
R
.
id
.
image_display
)
;
mImageView
.
setOnClickListener
(
new
OnClickListener
(
)
{
@
Override
public
void
onClick
(
View
v
)
{
Bundle
arguments
=
new
Bundle
(
)
;
Fragment
fragment
=
null
;
Log
.
d
(
"position adapter"
,
""
+
position
)
;
Product
product
=
(
Product
)
products
.
get
(
position
)
;
arguments
.
putParcelable
(
"singleProduct"
,
product
)
;
// Start a new fragment
fragment
=
new
ProductDetailFragment
(
)
;
fragment
.
setArguments
(
arguments
)
;
FragmentTransaction
transaction
=
activity
.
getSupportFragmentManager
(
)
.
beginTransaction
(
)
;
transaction
.
replace
(
R
.
id
.
content_frame
,
fragment
,
ProductDetailFragment
.
ARG_ITEM_ID
)
;
transaction
.
addToBackStack
(
ProductDetailFragment
.
ARG_ITEM_ID
)
;
transaction
.
commit
(
)
;
}
}
)
;
imageLoader
.
displayImage
(
(
(
Product
)
products
.
get
(
position
)
)
.
getImageUrl
(
)
,
mImageView
,
options
,
imageListener
)
;
container
.
addView
(
view
)
;
return
view
;
}
@
Override
public
void
destroyItem
(
ViewGroup
container
,
int
position
,
Object
object
)
{
container
.
removeView
(
(
View
)
object
)
;
}
@
Override
public
boolean
isViewFromObject
(
View
view
,
Object
object
)
{
return
view
==
object
;
}
private
static
class
ImageDisplayListener
extends
SimpleImageLoadingListener
{
static
final
List
<
String
>
displayedImages
=
Collections
.
synchronizedList
(
new
LinkedList
<
String
>
(
)
)
;
@
Override
public
void
onLoadingComplete
(
String
imageUri
,
View
view
,
Bitmap
loadedImage
)
{
if
(
loadedImage
!=
null
)
{
ImageView
imageView
=
(
ImageView
)
view
;
boolean
firstDisplay
=
!
displayedImages
.
contains
(
imageUri
)
;
if
(
firstDisplay
)
{
FadeInBitmapDisplayer
.
animate
(
imageView
,
500
)
;
displayedImages
.
add
(
imageUri
)
;
}
}
}
}
}
|
HomeFragment
In src folder, create a new class HomeFragment in the package com.androidopentutorials.imageslideshow.fragment .
- ViewPager.setCurrentItem() is used to animate screen slides automatically.
- We use Handler to make ViewPager auto slide after five (5) seconds.
- If the user slides the screen then we make ViewPager auto slide after ten (10) seconds.
Steps:
- In onResume(), if there are no products (==null) it sends a request where it executes a background AsyncTask to read remote JSON. It parses this JSON using the JsonReader.getHome() and returns list of products. In onPostExecute() it create ImageSlideAdapter and sets it in ViewPager.
- For ViewPager, we set touch listener and for MotionEvent.ACTION_UP (which is executed on ViewPager touch release) we post a runnable to the handler queue to be executed after ten (10) seconds which changes teh slide to next image.
- We also set a page change listener which changes the image name to reflect the current image view.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
|
package
com
.
androidopentutorials
.
imageslideshow
.
fragment
;
import
java
.
io
.
IOException
;
import
java
.
lang
.
ref
.
WeakReference
;
import
java
.
util
.
List
;
import
org
.
json
.
JSONObject
;
import
com
.
androidopentutorials
.
imageslideshow
.
R
;
import
com
.
androidopentutorials
.
imageslideshow
.
adapter
.
ImageSlideAdapter
;
import
com
.
androidopentutorials
.
imageslideshow
.
bean
.
Product
;
import
com
.
androidopentutorials
.
imageslideshow
.
json
.
GetJSONObject
;
import
com
.
androidopentutorials
.
imageslideshow
.
json
.
JsonReader
;
import
com
.
androidopentutorials
.
imageslideshow
.
utils
.
CheckNetworkConnection
;
import
com
.
androidopentutorials
.
imageslideshow
.
utils
.
CirclePageIndicator
;
import
com
.
androidopentutorials
.
imageslideshow
.
utils
.
PageIndicator
;
import
com
.
androidopentutorials
.
imageslideshow
.
utils
.
TagName
;
import
android
.
app
.
Activity
;
import
android
.
app
.
AlertDialog
;
import
android
.
content
.
DialogInterface
;
import
android
.
os
.
AsyncTask
;
import
android
.
os
.
Bundle
;
import
android
.
os
.
Handler
;
import
android
.
support
.
v4
.
app
.
Fragment
;
import
android
.
support
.
v4
.
app
.
FragmentActivity
;
import
android
.
support
.
v4
.
view
.
ViewPager
;
import
android
.
support
.
v4
.
view
.
ViewPager
.
OnPageChangeListener
;
import
android
.
view
.
LayoutInflater
;
import
android
.
view
.
MotionEvent
;
import
android
.
view
.
View
;
import
android
.
view
.
View
.
OnTouchListener
;
import
android
.
view
.
ViewGroup
;
import
android
.
widget
.
TextView
;
public
class
HomeFragment
extends
Fragment
{
public
static
final
String
ARG_ITEM_ID
=
"home_fragment"
;
private
static
final
long
ANIM_VIEWPAGER_DELAY
=
5000
;
private
static
final
long
ANIM_VIEWPAGER_DELAY_USER_VIEW
=
10000
;
// UI References
private
ViewPager
mViewPager
;
TextView
imgNameTxt
;
PageIndicator
mIndicator
;
AlertDialog
alertDialog
;
List
<
Product
>
products
;
RequestImgTask
task
;
boolean
stopSliding
=
false
;
String
message
;
private
Runnable
animateViewPager
;
private
Handler
handler
;
String
url
=
"http://192.168.3.119:8080/products.json"
;
FragmentActivity
activity
;
@
Override
public
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
)
;
activity
=
getActivity
(
)
;
}
@
Override
public
View
onCreateView
(
LayoutInflater
inflater
,
ViewGroup
container
,
Bundle
savedInstanceState
)
{
View
view
=
inflater
.
inflate
(
R
.
layout
.
fragment_home
,
container
,
false
)
;
findViewById
(
view
)
;
mIndicator
.
setOnPageChangeListener
(
new
PageChangeListener
(
)
)
;
mViewPager
.
setOnPageChangeListener
(
new
PageChangeListener
(
)
)
;
mViewPager
.
setOnTouchListener
(
new
OnTouchListener
(
)
{
@
Override
public
boolean
onTouch
(
View
v
,
MotionEvent
event
)
{
v
.
getParent
(
)
.
requestDisallowInterceptTouchEvent
(
true
)
;
switch
(
event
.
getAction
(
)
)
{
case
MotionEvent
.
ACTION_CANCEL
:
break
;
case
MotionEvent
.
ACTION_UP
:
// calls when touch release on ViewPager
if
(
products
!=
null
&&
products
.
size
(
)
!=
0
)
{
stopSliding
=
false
;
runnable
(
products
.
size
(
)
)
;
handler
.
postDelayed
(
animateViewPager
,
ANIM_VIEWPAGER_DELAY_USER_VIEW
)
;
}
break
;
case
MotionEvent
.
ACTION_MOVE
:
// calls when ViewPager touch
if
(
handler
!=
null
&&
stopSliding
==
false
)
{
stopSliding
=
true
;
handler
.
removeCallbacks
(
animateViewPager
)
;
}
break
;
}
return
false
;
}
}
)
;
return
view
;
}
private
void
findViewById
(
View
view
)
{
mViewPager
=
(
ViewPager
)
view
.
findViewById
(
R
.
id
.
view_pager
)
;
mIndicator
=
(
CirclePageIndicator
)
view
.
findViewById
(
R
.
id
.
indicator
)
;
imgNameTxt
=
(
TextView
)
view
.
findViewById
(
R
.
id
.
img_name
)
;
}
public
void
runnable
(
final
int
size
)
{
handler
=
new
Handler
(
)
;
animateViewPager
=
new
Runnable
(
)
{
public
void
run
(
)
{
if
(
!
stopSliding
)
{
if
(
mViewPager
.
getCurrentItem
(
)
==
size
-
1
)
{
mViewPager
.
setCurrentItem
(
0
)
;
}
else
{
mViewPager
.
setCurrentItem
(
mViewPager
.
getCurrentItem
(
)
+
1
,
true
)
;
}
handler
.
postDelayed
(
animateViewPager
,
ANIM_VIEWPAGER_DELAY
)
;
}
}
}
;
}
@
Override
public
void
onResume
(
)
{
if
(
products
==
null
)
{
sendRequest
(
)
;
}
else
{
mViewPager
.
setAdapter
(
new
ImageSlideAdapter
(
activity
,
products
,
HomeFragment
.
this
)
)
;
mIndicator
.
setViewPager
(
mViewPager
)
;
imgNameTxt
.
setText
(
""
+
(
(
Product
)
products
.
get
(
mViewPager
.
getCurrentItem
(
)
)
)
.
getName
(
)
)
;
runnable
(
products
.
size
(
)
)
;
//Re-run callback
handler
.
postDelayed
(
animateViewPager
,
ANIM_VIEWPAGER_DELAY
)
;
}
super
.
onResume
(
)
;
}
@
Override
public
void
onPause
(
)
{
if
(
task
!=
null
)
task
.
cancel
(
true
)
;
if
(
handler
!=
null
)
{
//Remove callback
handler
.
removeCallbacks
(
animateViewPager
)
;
}
super
.
onPause
(
)
;
}
private
void
sendRequest
(
)
{
if
(
CheckNetworkConnection
.
isConnectionAvailable
(
activity
)
)
{
task
=
new
RequestImgTask
(
activity
)
;
task
.
execute
(
url
)
;
}
else
{
message
=
getResources
(
)
.
getString
(
R
.
string
.
no_internet_connection
)
;
showAlertDialog
(
message
,
true
)
;
}
}
public
void
showAlertDialog
(
String
message
,
final
boolean
finish
)
{
alertDialog
=
new
AlertDialog
.
Builder
(
activity
)
.
create
(
)
;
alertDialog
.
setMessage
(
message
)
;
alertDialog
.
setCancelable
(
false
)
;
alertDialog
.
setButton
(
AlertDialog
.
BUTTON_POSITIVE
,
"OK"
,
new
DialogInterface
.
OnClickListener
(
)
{
public
void
onClick
(
DialogInterface
dialog
,
int
which
)
{
dialog
.
dismiss
(
)
;
if
(
finish
)
activity
.
finish
(
)
;
}
}
)
;
alertDialog
.
show
(
)
;
}
private
class
PageChangeListener
implements
OnPageChangeListener
{
@
Override
public
void
onPageScrollStateChanged
(
int
state
)
{
if
(
state
==
ViewPager
.
SCROLL_STATE_IDLE
)
{
if
(
products
!=
null
)
{
imgNameTxt
.
setText
(
""
+
(
(
Product
)
products
.
get
(
mViewPager
.
getCurrentItem
(
)
)
)
.
getName
(
)
)
;
}
}
}
@
Override
public
void
onPageScrolled
(
int
arg0
,
float
arg1
,
int
arg2
)
{
}
@
Override
public
void
onPageSelected
(
int
arg0
)
{
}
}
@
Override
public
void
onSaveInstanceState
(
Bundle
outState
)
{
super
.
onSaveInstanceState
(
outState
)
;
}
private
class
RequestImgTask
extends
AsyncTask
<
String
,
Void
,
List
<
Product
>>
{
private
final
WeakReference
<
Activity
>
activityWeakRef
;
Throwable
error
;
public
RequestImgTask
(
Activity
context
)
{
this
.
activityWeakRef
=
new
WeakReference
<
Activity
>
(
context
)
;
}
@
Override
protected
void
onPreExecute
(
)
{
super
.
onPreExecute
(
)
;
}
@
Override
protected
List
<
Product
>
doInBackground
(
String
.
.
.
urls
)
{
try
{
JSONObject
jsonObject
=
getJsonObject
(
urls
[
0
]
)
;
if
(
jsonObject
!=
null
)
{
boolean
status
=
jsonObject
.
getBoolean
(
TagName
.
TAG_STATUS
)
;
if
(
status
)
{
JSONObject
jsonData
=
jsonObject
.
getJSONObject
(
TagName
.
TAG_DATA
)
;
if
(
jsonData
!=
null
)
{
products
=
JsonReader
.
getHome
(
jsonData
)
;
}
else
{
message
=
jsonObject
.
getString
(
TagName
.
TAG_DATA
)
;
}
}
else
{
message
=
jsonObject
.
getString
(
TagName
.
TAG_DATA
)
;
}
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
)
;
}
return
products
;
}
/**
* It returns jsonObject for the specified url.
*
* @param url
* @return JSONObject
*/
public
JSONObject
getJsonObject
(
String
url
)
{
JSONObject
jsonObject
=
null
;
try
{
jsonObject
=
GetJSONObject
.
getJSONObject
(
url
)
;
}
catch
(
Exception
e
)
{
}
return
jsonObject
;
}
@
Override
protected
void
onPostExecute
(
List
<
Product
>
result
)
{
super
.
onPostExecute
(
result
)
;
if
(
activityWeakRef
!=
null
&&
!
activityWeakRef
.
get
(
)
.
isFinishing
(
)
)
{
if
(
error
!=
null
&&
error
instanceof
IOException
)
{
message
=
getResources
(
)
.
getString
(
R
.
string
.
time_out
)
;
showAlertDialog
(
message
,
true
)
;
}
else
if
(
error
!=
null
)
{
message
=
getResources
(
)
.
getString
(
R
.
string
.
error_occured
)
;
showAlertDialog
(
message
,
true
)
;
}
else
{
products
=
result
;
if
(
result
!=
null
)
{
if
(
products
!=
null
&&
products
.
size
(
)
!=
0
)
{
mViewPager
.
setAdapter
(
new
ImageSlideAdapter
(
activity
,
products
,
HomeFragment
.
this
)
)
;
mIndicator
.
setViewPager
(
mViewPager
)
;
imgNameTxt
.
setText
(
""
+
(
(
Product
)
products
.
get
(
mViewPager
.
getCurrentItem
(
)
)
)
.
getName
(
)
)
;
runnable
(
products
.
size
(
)
)
;
handler
.
postDelayed
(
animateViewPager
,
ANIM_VIEWPAGER_DELAY
)
;
}
else
{
imgNameTxt
.
setText
(
"No Products"
)
;
}
}
else
{
}
}
}
}
}
}
|
ProductDetailFragment
In src folder, create a new class ProductDetailFragment in the package com.androidopentutorials.imageslideshow.fragment . This class gets a single product from bundle and displays product image, id and name.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
package
com
.
androidopentutorials
.
imageslideshow
.
fragment
;
import
java
.
util
.
Collections
;
import
java
.
util
.
LinkedList
;
import
java
.
util
.
List
;
import
android
.
app
.
Activity
;
import
android
.
graphics
.
Bitmap
;
import
android
.
os
.
Bundle
;
import
android
.
support
.
v4
.
app
.
Fragment
;
import
android
.
view
.
LayoutInflater
;
import
android
.
view
.
View
;
import
android
.
view
.
ViewGroup
;
import
android
.
widget
.
ImageView
;
import
android
.
widget
.
TextView
;
import
com
.
androidopentutorials
.
imageslideshow
.
R
;
import
com
.
androidopentutorials
.
imageslideshow
.
bean
.
Product
;
import
com
.
nostra13
.
universalimageloader
.
core
.
DisplayImageOptions
;
import
com
.
nostra13
.
universalimageloader
.
core
.
ImageLoader
;
import
com
.
nostra13
.
universalimageloader
.
core
.
assist
.
ImageLoadingListener
;
import
com
.
nostra13
.
universalimageloader
.
core
.
assist
.
SimpleImageLoadingListener
;
import
com
.
nostra13
.
universalimageloader
.
core
.
display
.
FadeInBitmapDisplayer
;
public
class
ProductDetailFragment
extends
Fragment
{
TextView
pdtIdTxt
;
TextView
pdtNameTxt
;
ImageView
pdtImg
;
Activity
activity
;
ImageLoader
imageLoader
=
ImageLoader
.
getInstance
(
)
;
DisplayImageOptions
options
;
private
ImageLoadingListener
imageListener
;
Product
product
;
public
static
final
String
ARG_ITEM_ID
=
"pdt_detail_fragment"
;
@
Override
public
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
)
;
activity
=
getActivity
(
)
;
options
=
new
DisplayImageOptions
.
Builder
(
)
.
showImageOnFail
(
R
.
drawable
.
ic_launcher
)
.
showStubImage
(
R
.
drawable
.
ic_launcher
)
.
showImageForEmptyUri
(
R
.
drawable
.
ic_launcher
)
.
cacheInMemory
(
)
.
cacheOnDisc
(
)
.
build
(
)
;
imageListener
=
new
ImageDisplayListener
(
)
;
}
@
Override
public
View
onCreateView
(
LayoutInflater
inflater
,
ViewGroup
container
,
Bundle
savedInstanceState
)
{
View
view
=
inflater
.
inflate
(
R
.
layout
.
fragment_pdt_detail
,
container
,
false
)
;
findViewById
(
view
)
;
Bundle
bundle
=
this
.
getArguments
(
)
;
if
(
bundle
!=
null
)
{
product
=
bundle
.
getParcelable
(
"singleProduct"
)
;
setProductItem
(
product
)
;
}
return
view
;
}
private
void
findViewById
(
View
view
)
{
pdtNameTxt
=
(
TextView
)
view
.
findViewById
(
R
.
id
.
pdt_name
)
;
pdtIdTxt
=
(
TextView
)
view
.
findViewById
(
R
.
id
.
product_id_text
)
;
pdtImg
=
(
ImageView
)
view
.
findViewById
(
R
.
id
.
product_detail_img
)
;
}
private
static
class
ImageDisplayListener
extends
SimpleImageLoadingListener
{
static
final
List
<
String
>
displayedImages
=
Collections
.
synchronizedList
(
new
LinkedList
<
String
>
(
)
)
;
@
Override
public
void
onLoadingComplete
(
String
imageUri
,
View
view
,
Bitmap
loadedImage
)
{
if
(
loadedImage
!=
null
)
{
ImageView
imageView
=
(
ImageView
)
view
;
boolean
firstDisplay
=
!
displayedImages
.
contains
(
imageUri
)
;
if
(
firstDisplay
)
{
FadeInBitmapDisplayer
.
animate
(
imageView
,
500
)
;
displayedImages
.
add
(
imageUri
)
;
}
}
}
}
private
void
setProductItem
(
Product
resultProduct
)
{
pdtNameTxt
.
setText
(
""
+
resultProduct
.
getName
(
)
)
;
pdtIdTxt
.
setText
(
"Product Id: "
+
resultProduct
.
getId
(
)
)
;
imageLoader
.
displayImage
(
resultProduct
.
getImageUrl
(
)
,
pdtImg
,
options
,
imageListener
)
;
}
}
|
MainActivity
In src folder, create a new class MainActivity in the package com.androidopentutorials.imageslideshow .
- This is the main activity class.
- When the app starts, it begins a new FragmentTransaction and starts HomeFragment.
- It handles proper back navigation of fragments on back key pressed by overriding onBackPressed() .
- It handles fragment orientation changes and retains the fragment state by overriding onSaveInstanceState() .
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
package
com
.
androidopentutorials
.
imageslideshow
;
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
.
FragmentTransaction
;
import
android
.
view
.
Menu
;
import
com
.
androidopentutorials
.
imageslideshow
.
fragment
.
HomeFragment
;
import
com
.
androidopentutorials
.
imageslideshow
.
fragment
.
ProductDetailFragment
;
public
class
MainActivity
extends
FragmentActivity
{
private
Fragment
contentFragment
;
HomeFragment
homeFragment
;
ProductDetailFragment
pdtDetailFragment
;
@
Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
)
;
setContentView
(
R
.
layout
.
activity_main
)
;
FragmentManager
fragmentManager
=
getSupportFragmentManager
(
)
;
if
(
savedInstanceState
!=
null
)
{
if
(
savedInstanceState
.
containsKey
(
"content"
)
)
{
String
content
=
savedInstanceState
.
getString
(
"content"
)
;
if
(
content
.
equals
(
ProductDetailFragment
.
ARG_ITEM_ID
)
)
{
if
(
fragmentManager
.
findFragmentByTag
(
ProductDetailFragment
.
ARG_ITEM_ID
)
!=
null
)
{
contentFragment
=
fragmentManager
.
findFragmentByTag
(
ProductDetailFragment
.
ARG_ITEM_ID
)
;
}
}
}
if
(
fragmentManager
.
findFragmentByTag
(
HomeFragment
.
ARG_ITEM_ID
)
!=
null
)
{
homeFragment
=
(
HomeFragment
)
fragmentManager
.
findFragmentByTag
(
HomeFragment
.
ARG_ITEM_ID
)
;
contentFragment
=
homeFragment
;
}
}
else
{
homeFragment
=
new
HomeFragment
(
)
;
switchContent
(
homeFragment
,
HomeFragment
.
ARG_ITEM_ID
)
;
}
}
@
Override
protected
void
onSaveInstanceState
(
Bundle
outState
)
{
if
(
contentFragment
instanceof
HomeFragment
)
{
outState
.
putString
(
"content"
,
HomeFragment
.
ARG_ITEM_ID
)
;
}
else
{
outState
.
putString
(
"content"
,
ProductDetailFragment
.
ARG_ITEM_ID
)
;
}
super
.
onSaveInstanceState
(
outState
)
;
}
public
void
switchContent
(
Fragment
fragment
,
String
tag
)
{
FragmentManager
fragmentManager
=
getSupportFragmentManager
(
)
;
while
(
fragmentManager
.
popBackStackImmediate
(
)
)
;
if
(
fragment
!=
null
)
{
FragmentTransaction
transaction
=
fragmentManager
.
beginTransaction
(
)
;
transaction
.
replace
(
R
.
id
.
content_frame
,
fragment
,
tag
)
;
// Only ProductDetailFragment is added to the back stack.
if
(
!
(
fragment
instanceof
HomeFragment
)
)
{
transaction
.
addToBackStack
(
tag
)
;
}
transaction
.
commit
(
)
;
contentFragment
=
fragment
;
}
}
@
Override
public
void
onBackPressed
(
)
{
FragmentManager
fm
=
getSupportFragmentManager
(
)
;
if
(
fm
.
getBackStackEntryCount
(
)
>
0
)
{
super
.
onBackPressed
(
)
;
}
else
if
(
contentFragment
instanceof
HomeFragment
||
fm
.
getBackStackEntryCount
(
)
==
0
)
{
finish
(
)
;
}
}
@
Override
public
boolean
onCreateOptionsMenu
(
Menu
menu
)
{
getMenuInflater
(
)
.
inflate
(
R
.
menu
.
main
,
menu
)
;
return
true
;
}
}
|
AppData
In src folder, create a new class AppData in the package com.androidopentutorials.imageslideshow .
Universal ImageLoader configuration (ImageLoaderConfiguration) is global for application hence create a class which extends android.app.Application and create a global configuration and initialize ImageLoader.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
package
com
.
androidopentutorials
.
imageslideshow
;
import
android
.
app
.
Application
;
import
android
.
content
.
Context
;
import
android
.
graphics
.
Bitmap
;
import
android
.
os
.
Build
;
import
android
.
os
.
StrictMode
;
import
android
.
view
.
View
;
import
com
.
nostra13
.
universalimageloader
.
cache
.
disc
.
naming
.
Md5FileNameGenerator
;
import
com
.
nostra13
.
universalimageloader
.
core
.
DisplayImageOptions
;
import
com
.
nostra13
.
universalimageloader
.
core
.
ImageLoader
;
import
com
.
nostra13
.
universalimageloader
.
core
.
ImageLoaderConfiguration
;
import
com
.
nostra13
.
universalimageloader
.
core
.
assist
.
ImageScaleType
;
import
com
.
nostra13
.
universalimageloader
.
core
.
assist
.
QueueProcessingType
;
import
com
.
nostra13
.
universalimageloader
.
core
.
display
.
FadeInBitmapDisplayer
;
public
class
AppData
extends
Application
{
public
static
final
boolean
DEVELOPER_MODE
=
false
;
View
footerView
;
@
SuppressWarnings
(
"unused"
)
public
void
onCreate
(
)
{
super
.
onCreate
(
)
;
if
(
DEVELOPER_MODE
&&
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
GINGERBREAD
)
{
StrictMode
.
setThreadPolicy
(
new
StrictMode
.
ThreadPolicy
.
Builder
(
)
.
detectAll
(
)
.
penaltyDialog
(
)
.
build
(
)
)
;
StrictMode
.
setVmPolicy
(
new
StrictMode
.
VmPolicy
.
Builder
(
)
.
detectAll
(
)
.
penaltyDeath
(
)
.
build
(
)
)
;
}
initImageLoader
(
getApplicationContext
(
)
)
;
}
public
static
void
initImageLoader
(
Context
context
)
{
DisplayImageOptions
options
=
new
DisplayImageOptions
.
Builder
(
)
.
showImageForEmptyUri
(
R
.
drawable
.
ic_empty
)
.
showImageOnFail
(
R
.
drawable
.
ic_error
)
.
resetViewBeforeLoading
(
)
.
cacheOnDisc
(
)
.
imageScaleType
(
ImageScaleType
.
EXACTLY
)
.
bitmapConfig
(
Bitmap
.
Config
.
RGB_565
)
.
displayer
(
new
FadeInBitmapDisplayer
(
300
)
)
.
build
(
)
;
ImageLoaderConfiguration
config
=
new
ImageLoaderConfiguration
.
Builder
(
context
)
.
threadPriority
(
Thread
.
NORM_PRIORITY
-
2
)
.
denyCacheImageMultipleSizesInMemory
(
)
.
discCacheFileNameGenerator
(
new
Md5FileNameGenerator
(
)
)
.
defaultDisplayImageOptions
(
options
)
.
tasksProcessingOrder
(
QueueProcessingType
.
LIFO
)
.
build
(
)
;
ImageLoader
.
getInstance
(
)
.
init
(
config
)
;
}
}
|
AndroidManifest.xml
Define the activity in AndroidManifest.xml file. To access internet from Android application set the android.permission.INTERNET permission in manifest file as shown below. In <application> element specify android:name by providing the fully qualified name of Application subclass ( AppData ). When the application process is started, this class is instantiated before any of the application’s components.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
manifest
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
package
=
"com.androidopentutorials.imageslideshow"
android
:
versionCode
=
"1"
android
:
versionName
=
"1.0"
>
<
uses
-
sdk
android
:
minSdkVersion
=
"14"
android
:
targetSdkVersion
=
"19"
/
>
<
uses
-
permission
android
:
name
=
"android.permission.INTERNET"
/
>
<
uses
-
permission
android
:
name
=
"android.permission.ACCESS_NETWORK_STATE"
/
>
<
application
android
:
name
=
"com.androidopentutorials.imageslideshow.AppData"
android
:
allowBackup
=
"true"
android
:
icon
=
"@drawable/ic_launcher"
android
:
label
=
"@string/app_name"
android
:
theme
=
"@style/AppTheme"
>
<
activity
android
:
name
=
"com.androidopentutorials.imageslideshow.MainActivity"
android
:
label
=
"@string/app_name"
>
<
intent
-
filter
>
<
action
android
:
name
=
"android.intent.action.MAIN"
/
>
<
category
android
:
name
=
"android.intent.category.LAUNCHER"
/
>
<
/
intent
-
filter
>
<
/
activity
>
<
/
application
>
<
/
manifest
>
|
Pingback: Android Image Gallery using ViewPager » the Open Tutorials
Pingback: Fragments not loading in my project | 我爱源码网
Pingback: 안드로이드 ViewPager | 한글로의 개발노트
Pingback: Tổng hợp android | 3s
Pingback: Getting NullPointerException in Activity where i'm receiving Json data [duplicate] - BlogoSfera
Pingback: Imave View Fill Empty Space ViewPager Android - BlogoSfera
Pingback: Image View Fill Empty Space ViewPager Android - BlogoSfera
Pingback: Android Templates and advance concepts – vaidehipjoshi25
Pingback: ic218 » Полезные ссылки для Android разработчика
Pingback: Image View Fill Empty Space ViewPager Android - Tutorial Guruji