├── ic_launcher-web.png ├── Custom Components.pptx ├── assets └── fonts │ ├── Lobster.ttf │ ├── ComingSoon.ttf │ ├── Dosis-Bold.ttf │ ├── Dosis-Light.ttf │ ├── Lora-Bold.ttf │ ├── Lora-Italic.ttf │ ├── Abel-Regular.ttf │ ├── Dosis-Medium.ttf │ ├── Dosis-Regular.ttf │ ├── Lora-Regular.ttf │ ├── Unkempt-Bold.ttf │ ├── ChangaOne-Italic.ttf │ ├── Dosis-ExtraBold.ttf │ ├── Dosis-ExtraLight.ttf │ ├── Dosis-SemiBold.ttf │ ├── JosefinSans-Bold.ttf │ ├── JosefinSans-Thin.ttf │ ├── Lora-BoldItalic.ttf │ ├── ShadowsIntoLight.ttf │ ├── Unkempt-Regular.ttf │ ├── ChangaOne-Regular.ttf │ ├── DancingScript-Bold.ttf │ ├── JosefinSans-Italic.ttf │ ├── JosefinSans-Light.ttf │ ├── DancingScript-Regular.ttf │ ├── JosefinSans-Regular.ttf │ ├── JosefinSans-SemiBold.ttf │ ├── RobotoCondensed-Bold.ttf │ ├── RobotoCondensed-Light.ttf │ ├── JosefinSans-BoldItalic.ttf │ ├── JosefinSans-LightItalic.ttf │ ├── JosefinSans-ThinItalic.ttf │ ├── RobotoCondensed-Italic.ttf │ ├── RobotoCondensed-Regular.ttf │ ├── UbuntuCondensed-Regular.ttf │ ├── JosefinSans-SemiBoldItalic.ttf │ ├── RobotoCondensed-BoldItalic.ttf │ └── RobotoCondensed-LightItalic.ttf ├── libs └── android-support-v4.jar ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ └── ic_launcher.png ├── drawable-xxhdpi │ └── ic_launcher.png ├── values │ ├── dimens.xml │ ├── attrs.xml │ ├── styles.xml │ └── strings.xml ├── layout │ ├── fr_draw.xml │ ├── ac_main.xml │ ├── fr_animation.xml │ ├── fr_code_smells.xml │ ├── fr_fonts_styled.xml │ ├── fr_fonts.xml │ └── fr_standard.xml ├── values-sw600dp │ └── dimens.xml ├── values-sw720dp-land │ └── dimens.xml └── values-v11 │ └── styles.xml ├── .settings └── org.eclipse.jdt.core.prefs ├── .gitignore ├── src └── com │ └── pixplicity │ └── devfest │ ├── widgets │ ├── SimpleAnimatedViewSlow2.java │ ├── SimpleAnimatedViewSlow1.java │ ├── FontButton.java │ ├── FontEditText.java │ ├── BrokenViewGroup.java │ ├── FontTextView.java │ ├── DrawingView.java │ └── SimpleAnimatedView.java │ ├── fragments │ ├── DrawingFragment.java │ ├── Fonts1Fragment.java │ ├── Fonts2Fragment.java │ ├── StandardFragment.java │ ├── SimpleAnimatedViewFragment.java │ └── CodeSmellsFragment.java │ ├── util │ └── FontUtil.java │ └── MainActivity.java ├── .classpath ├── project.properties ├── README.md ├── proguard-project.txt ├── .project └── AndroidManifest.xml /ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/ic_launcher-web.png -------------------------------------------------------------------------------- /Custom Components.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/Custom Components.pptx -------------------------------------------------------------------------------- /assets/fonts/Lobster.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Lobster.ttf -------------------------------------------------------------------------------- /assets/fonts/ComingSoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/ComingSoon.ttf -------------------------------------------------------------------------------- /assets/fonts/Dosis-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Dosis-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/Dosis-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Dosis-Light.ttf -------------------------------------------------------------------------------- /assets/fonts/Lora-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Lora-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/Lora-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Lora-Italic.ttf -------------------------------------------------------------------------------- /libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/libs/android-support-v4.jar -------------------------------------------------------------------------------- /assets/fonts/Abel-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Abel-Regular.ttf -------------------------------------------------------------------------------- /assets/fonts/Dosis-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Dosis-Medium.ttf -------------------------------------------------------------------------------- /assets/fonts/Dosis-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Dosis-Regular.ttf -------------------------------------------------------------------------------- /assets/fonts/Lora-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Lora-Regular.ttf -------------------------------------------------------------------------------- /assets/fonts/Unkempt-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Unkempt-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/ChangaOne-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/ChangaOne-Italic.ttf -------------------------------------------------------------------------------- /assets/fonts/Dosis-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Dosis-ExtraBold.ttf -------------------------------------------------------------------------------- /assets/fonts/Dosis-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Dosis-ExtraLight.ttf -------------------------------------------------------------------------------- /assets/fonts/Dosis-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Dosis-SemiBold.ttf -------------------------------------------------------------------------------- /assets/fonts/JosefinSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/JosefinSans-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/JosefinSans-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/JosefinSans-Thin.ttf -------------------------------------------------------------------------------- /assets/fonts/Lora-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Lora-BoldItalic.ttf -------------------------------------------------------------------------------- /assets/fonts/ShadowsIntoLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/ShadowsIntoLight.ttf -------------------------------------------------------------------------------- /assets/fonts/Unkempt-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/Unkempt-Regular.ttf -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /assets/fonts/ChangaOne-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/ChangaOne-Regular.ttf -------------------------------------------------------------------------------- /assets/fonts/DancingScript-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/DancingScript-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/JosefinSans-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/JosefinSans-Italic.ttf -------------------------------------------------------------------------------- /assets/fonts/JosefinSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/JosefinSans-Light.ttf -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /assets/fonts/DancingScript-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/DancingScript-Regular.ttf -------------------------------------------------------------------------------- /assets/fonts/JosefinSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/JosefinSans-Regular.ttf -------------------------------------------------------------------------------- /assets/fonts/JosefinSans-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/JosefinSans-SemiBold.ttf -------------------------------------------------------------------------------- /assets/fonts/RobotoCondensed-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/RobotoCondensed-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/RobotoCondensed-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/RobotoCondensed-Light.ttf -------------------------------------------------------------------------------- /assets/fonts/JosefinSans-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/JosefinSans-BoldItalic.ttf -------------------------------------------------------------------------------- /assets/fonts/JosefinSans-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/JosefinSans-LightItalic.ttf -------------------------------------------------------------------------------- /assets/fonts/JosefinSans-ThinItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/JosefinSans-ThinItalic.ttf -------------------------------------------------------------------------------- /assets/fonts/RobotoCondensed-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/RobotoCondensed-Italic.ttf -------------------------------------------------------------------------------- /assets/fonts/RobotoCondensed-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/RobotoCondensed-Regular.ttf -------------------------------------------------------------------------------- /assets/fonts/UbuntuCondensed-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/UbuntuCondensed-Regular.ttf -------------------------------------------------------------------------------- /assets/fonts/JosefinSans-SemiBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/JosefinSans-SemiBoldItalic.ttf -------------------------------------------------------------------------------- /assets/fonts/RobotoCondensed-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/RobotoCondensed-BoldItalic.ttf -------------------------------------------------------------------------------- /assets/fonts/RobotoCondensed-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixplicity/android-custom-components/HEAD/assets/fonts/RobotoCondensed-LightItalic.ttf -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18sp 4 | 5 | 6 | 16dp 7 | 16dp 8 | 9 | -------------------------------------------------------------------------------- /res/layout/fr_draw.xml: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /res/values-sw600dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 18sp 10 | 11 | -------------------------------------------------------------------------------- /res/values-sw720dp-land/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 128dp 8 | 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | # Eclipse project files 19 | .classpath 20 | .project 21 | -------------------------------------------------------------------------------- /res/layout/ac_main.xml: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/widgets/SimpleAnimatedViewSlow2.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.widgets; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | 6 | public class SimpleAnimatedViewSlow2 extends SimpleAnimatedView { 7 | 8 | public SimpleAnimatedViewSlow2(Context context, AttributeSet attrs) { 9 | super(context, attrs); 10 | } 11 | 12 | @Override 13 | protected void nextFrame() { 14 | postDelayed(animator, FPS_DELAY); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /res/layout/fr_animation.xml: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-19 15 | -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/fragments/DrawingFragment.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.fragments; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.pixplicity.mobdevcon.R; 10 | 11 | 12 | public class DrawingFragment extends Fragment { 13 | 14 | @Override 15 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 16 | Bundle savedInstanceState) { 17 | View rootView = inflater.inflate(R.layout.fr_draw, container, 18 | false); 19 | return rootView; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/fragments/Fonts1Fragment.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.fragments; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.pixplicity.mobdevcon.R; 10 | 11 | /** 12 | * A fragment showcasing some custom components. 13 | */ 14 | public class Fonts1Fragment extends Fragment { 15 | 16 | public Fonts1Fragment() {} 17 | 18 | @Override 19 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 20 | Bundle savedInstanceState) { 21 | View rootView = inflater.inflate(R.layout.fr_fonts, container, 22 | false); 23 | return rootView; 24 | } 25 | } -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/fragments/Fonts2Fragment.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.fragments; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.pixplicity.mobdevcon.R; 10 | 11 | /** 12 | * A fragment showcasing some custom components. 13 | */ 14 | public class Fonts2Fragment extends Fragment { 15 | 16 | public Fonts2Fragment() {} 17 | 18 | @Override 19 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 20 | Bundle savedInstanceState) { 21 | View rootView = inflater.inflate(R.layout.fr_fonts_styled, 22 | container, false); 23 | return rootView; 24 | } 25 | } -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/fragments/StandardFragment.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.fragments; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.pixplicity.mobdevcon.R; 10 | 11 | /** 12 | * A fragment showcasing some standard components. 13 | */ 14 | public class StandardFragment extends Fragment { 15 | 16 | public StandardFragment() {} 17 | 18 | @Override 19 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 20 | Bundle savedInstanceState) { 21 | View rootView = inflater.inflate(R.layout.fr_standard, container, 22 | false); 23 | return rootView; 24 | } 25 | } -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/fragments/SimpleAnimatedViewFragment.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.fragments; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.pixplicity.mobdevcon.R; 10 | 11 | /** 12 | * A fragment showcasing some custom components. 13 | */ 14 | public class SimpleAnimatedViewFragment extends Fragment { 15 | 16 | public SimpleAnimatedViewFragment() {} 17 | 18 | @Override 19 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 20 | Bundle savedInstanceState) { 21 | View rootView = inflater.inflate(R.layout.fr_animation, container, 22 | false); 23 | return rootView; 24 | } 25 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Custom Components for Android 2 | =========== 3 | 4 | This application demos some custom components for Android. 5 | 6 | It's best understood in conjuction with Paul Lammertsma's talk, *Custom Components*. 7 | 8 | > Android offers a powerful model for building user interfaces, based on fundamental layout components View and ViewGroup. The platform includes a prebuilt set that you can use to construct your UI, but making your own may be easier than you think and it will make your code around complex UIs cleaner and much easier to understand. 9 | > 10 | > In this talk I'll explain how some of Android's widgets and layouts are put together and how you can expand on them. I'll demonstrate creating a custom font widget, an animated view, and how everything neatly fits together in layouts, themes, and yes, even inside Eclipse's graphical layout. 11 | -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/widgets/SimpleAnimatedViewSlow1.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.widgets; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.RectF; 7 | import android.util.AttributeSet; 8 | 9 | public class SimpleAnimatedViewSlow1 extends SimpleAnimatedView { 10 | 11 | public SimpleAnimatedViewSlow1(Context context, AttributeSet attrs) { 12 | super(context, attrs); 13 | } 14 | 15 | @Override 16 | protected void createPaints() { 17 | mPaintFg = new Paint(Paint.ANTI_ALIAS_FLAG); 18 | mPaintLn = new Paint(Paint.ANTI_ALIAS_FLAG); 19 | mPaintBg = new Paint(Paint.ANTI_ALIAS_FLAG); 20 | super.createPaints(); 21 | } 22 | 23 | @Override 24 | protected void onDraw(Canvas canvas) { 25 | createPaints(); 26 | super.onDraw(canvas); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/widgets/FontButton.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.widgets; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.Button; 6 | 7 | import com.pixplicity.devfest.util.FontUtil; 8 | 9 | public class FontButton extends Button { 10 | 11 | public FontButton(Context context) { 12 | super(context); 13 | FontTextView.init(this, context, null, 0); 14 | } 15 | 16 | public FontButton(Context context, AttributeSet attrs) { 17 | super(context, attrs); 18 | FontTextView.init(this, context, attrs, 0); 19 | } 20 | 21 | public FontButton(Context context, AttributeSet attrs, int defStyle) { 22 | super(context, attrs, defStyle); 23 | FontTextView.init(this, context, attrs, defStyle); 24 | } 25 | 26 | public void setTypeface(String typeface) { 27 | FontUtil.setTypeface(this, typeface); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/widgets/FontEditText.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.widgets; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.EditText; 6 | 7 | import com.pixplicity.devfest.util.FontUtil; 8 | 9 | public class FontEditText extends EditText { 10 | 11 | public FontEditText(Context context) { 12 | super(context); 13 | FontTextView.init(this, context, null, 0); 14 | } 15 | 16 | public FontEditText(Context context, AttributeSet attrs) { 17 | super(context, attrs); 18 | FontTextView.init(this, context, attrs, 0); 19 | } 20 | 21 | public FontEditText(Context context, AttributeSet attrs, int defStyle) { 22 | super(context, attrs, defStyle); 23 | FontTextView.init(this, context, attrs, defStyle); 24 | } 25 | 26 | public void setTypeface(String typeface) { 27 | FontUtil.setTypeface(this, typeface); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | devday 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/widgets/BrokenViewGroup.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.widgets; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.MotionEvent; 6 | import android.view.ViewGroup; 7 | import android.widget.LinearLayout; 8 | import android.widget.TextView; 9 | 10 | public class BrokenViewGroup extends LinearLayout { 11 | 12 | private TextView mViewToShowIfSpace; 13 | 14 | public BrokenViewGroup(Context context, AttributeSet attrs) { 15 | super(context, attrs); 16 | mViewToShowIfSpace = new TextView(context); 17 | mViewToShowIfSpace.setText("Hello world!"); 18 | } 19 | 20 | @Override 21 | // * 22 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 23 | super.onLayout(changed, l, t, r, b); 24 | if (mViewToShowIfSpace != null 25 | && b < ((ViewGroup) getParent()).getHeight()) { 26 | addView(mViewToShowIfSpace); 27 | mViewToShowIfSpace = null; 28 | } 29 | } 30 | 31 | @Override 32 | public boolean onTouchEvent(MotionEvent event) { 33 | requestLayout(); 34 | return super.onTouchEvent(event); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 15 | 16 | 17 | 20 | 21 | 26 | 27 | 30 | 31 | -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/widgets/FontTextView.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.widgets; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.widget.TextView; 7 | 8 | import com.pixplicity.devfest.util.FontUtil; 9 | import com.pixplicity.mobdevcon.R; 10 | 11 | public class FontTextView extends TextView { 12 | 13 | public FontTextView(Context context) { 14 | super(context); 15 | FontTextView.init(this, context, null, 0); 16 | } 17 | 18 | public FontTextView(Context context, AttributeSet attrs) { 19 | super(context, attrs); 20 | FontTextView.init(this, context, attrs, 0); 21 | } 22 | 23 | public FontTextView(Context context, AttributeSet attrs, int defStyle) { 24 | super(context, attrs, defStyle); 25 | FontTextView.init(this, context, attrs, defStyle); 26 | } 27 | 28 | protected static void init(TextView view, Context context, 29 | AttributeSet attrs, int defStyle) { 30 | if (attrs != null) { 31 | final TypedArray a = context.obtainStyledAttributes( 32 | attrs, R.styleable.FontTextView, defStyle, 0); 33 | final String typeface = 34 | a.getString(R.styleable.FontTextView_typeface); 35 | a.recycle(); 36 | 37 | FontUtil.setTypeface(view, typeface); 38 | } 39 | } 40 | 41 | public void setTypeface(String typeface) { 42 | FontUtil.setTypeface(this, typeface); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/util/FontUtil.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.util; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import android.content.Context; 7 | import android.graphics.Paint; 8 | import android.graphics.Typeface; 9 | import android.widget.TextView; 10 | 11 | public class FontUtil { 12 | 13 | private static final Map FONTS = new HashMap(); 14 | 15 | public static Typeface getTypeface(Context context, String typefaceName) { 16 | typefaceName = typefaceName.intern(); 17 | Typeface typeface = FONTS.get(typefaceName); 18 | if (typeface == null) { 19 | typeface = Typeface.createFromAsset( 20 | context.getAssets(), 21 | "fonts/" + typefaceName); 22 | FONTS.put(typefaceName, typeface); 23 | } 24 | return typeface; 25 | } 26 | 27 | public static void setTypeface(TextView view, String typeface) { 28 | if (typeface != null && !view.isInEditMode()) { 29 | setTypeface(view, getTypeface(view.getContext(), typeface)); 30 | } 31 | } 32 | 33 | public static void setTypefaceBad(TextView view, String typefaceName) { 34 | Typeface typeface = Typeface.createFromAsset( 35 | view.getContext().getAssets(), 36 | "fonts/" + typefaceName); 37 | setTypeface(view, typeface); 38 | } 39 | 40 | private static void setTypeface(TextView view, Typeface typeface) { 41 | view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG); 42 | view.setTypeface(typeface); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /res/layout/fr_code_smells.xml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | 18 | 23 | 24 | 28 | 29 | 34 | 35 | 41 | 42 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /res/layout/fr_fonts_styled.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | 16 | 22 | 23 | 28 | 29 | 34 | 35 | 40 | 41 | 46 | 47 | 50 | 51 | 60 | 61 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/widgets/DrawingView.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.widgets; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.Path; 8 | import android.graphics.Rect; 9 | import android.util.AttributeSet; 10 | import android.view.MotionEvent; 11 | import android.view.View; 12 | 13 | public class DrawingView extends View { 14 | 15 | private static final boolean QUAD_LINES = false; 16 | private static final float STROKE_WIDTH = 6f; 17 | private static final boolean INVALIDATE_REGION = true; 18 | 19 | private final Paint paint = new Paint(); 20 | private final Path path = new Path(); 21 | private float lastX = -1, lastY; 22 | 23 | public DrawingView(Context context, AttributeSet attrs) { 24 | super(context, attrs); 25 | 26 | paint.setAntiAlias(true); 27 | paint.setStrokeWidth(STROKE_WIDTH); 28 | paint.setColor(Color.BLACK); 29 | paint.setStyle(Paint.Style.STROKE); 30 | paint.setStrokeJoin(Paint.Join.ROUND); 31 | } 32 | 33 | @Override 34 | public boolean onTouchEvent(MotionEvent event) { 35 | Rect dirty = null; 36 | float x = event.getX(); 37 | float y = event.getY(); 38 | switch (event.getAction()) { 39 | case MotionEvent.ACTION_DOWN: 40 | path.moveTo(x, y); 41 | break; 42 | case MotionEvent.ACTION_MOVE: 43 | dirty = new Rect( 44 | (int) Math.floor(lastX), (int) Math.floor(lastY), 45 | (int) Math.floor(lastX), (int) Math.floor(lastY)); 46 | // Android batches touch events; see 47 | // http://corner.squareup.com/2010/07/smooth-signatures.html 48 | int historySize = event.getHistorySize(); 49 | for (int i = 0; i < historySize; i++) { 50 | float historicalX = event.getHistoricalX(i); 51 | float historicalY = event.getHistoricalY(i); 52 | lineTo(historicalX, historicalY, dirty); 53 | } 54 | lineTo(x, y, dirty); 55 | break; 56 | case MotionEvent.ACTION_UP: 57 | // Nothing to do 58 | break; 59 | } 60 | if (INVALIDATE_REGION && dirty != null) { 61 | int pad = (int) (STROKE_WIDTH / 2); 62 | invalidate(dirty.left - pad, dirty.top - pad, dirty.right + pad, dirty.bottom + pad); 63 | } else { 64 | invalidate(); 65 | } 66 | lastX = x; 67 | lastY = y; 68 | return true; 69 | } 70 | 71 | private void lineTo(float x, float y, Rect dirty) { 72 | if (INVALIDATE_REGION) { 73 | int pad = (int) (STROKE_WIDTH / 2); 74 | if (x < dirty.left) { 75 | dirty.left = (int) Math.floor(x); 76 | } else { 77 | dirty.right = (int) Math.ceil(x); 78 | } 79 | if (y < dirty.top) { 80 | dirty.top = (int) Math.floor(y); 81 | } else { 82 | dirty.bottom = (int) Math.ceil(y); 83 | } 84 | } 85 | if (QUAD_LINES) { 86 | path.quadTo(x, y, (lastX + x) / 2, (lastY + y) / 2); 87 | } else { 88 | path.lineTo(x, y); 89 | } 90 | } 91 | 92 | @Override 93 | protected void onDraw(Canvas canvas) { 94 | canvas.drawPath(path, paint); 95 | super.onDraw(canvas); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/fragments/CodeSmellsFragment.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.fragments; 2 | 3 | import java.text.NumberFormat; 4 | 5 | import android.app.Activity; 6 | import android.os.Bundle; 7 | import android.os.Handler; 8 | import android.support.v4.app.Fragment; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.AdapterView; 13 | import android.widget.AdapterView.OnItemSelectedListener; 14 | import android.widget.ArrayAdapter; 15 | import android.widget.Spinner; 16 | import android.widget.TextView; 17 | 18 | import com.pixplicity.devfest.widgets.SimpleAnimatedView; 19 | import com.pixplicity.mobdevcon.R; 20 | 21 | /** 22 | * A fragment showcasing some custom components. 23 | */ 24 | public class CodeSmellsFragment extends Fragment implements SimpleAnimatedView.FpsListener { 25 | 26 | private SimpleAnimatedView mAnim1; 27 | private SimpleAnimatedView mAnim2; 28 | private SimpleAnimatedView mAnim3; 29 | 30 | private TextView mFpsText; 31 | private float mFps; 32 | 33 | private final Handler mHandler = new Handler(); 34 | private final Runnable mFpsRunnable = new Runnable() { 35 | @Override 36 | public void run() { 37 | NumberFormat nf = NumberFormat.getInstance(); 38 | nf.setMaximumFractionDigits(1); 39 | mFpsText.setText(nf.format(mFps) + " fps"); 40 | mHandler.postDelayed(this, 200); 41 | } 42 | }; 43 | private Spinner mAnimSpinner; 44 | 45 | public CodeSmellsFragment() {} 46 | 47 | @Override 48 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 49 | Bundle savedInstanceState) { 50 | View rootView = inflater.inflate(R.layout.fr_code_smells, 51 | container, false); 52 | mAnimSpinner = (Spinner) rootView.findViewById(R.id.sp_switch); 53 | String[] animList = new String[]{"Normal", "Code smell 1", "Code smell 2"}; 54 | mAnimSpinner.setAdapter(new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, animList)); 55 | mAnimSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { 56 | 57 | @Override 58 | public void onItemSelected(AdapterView parent, View view, 59 | int position, long id) { 60 | nextSmell(position); 61 | } 62 | 63 | @Override 64 | public void onNothingSelected(AdapterView parent) { 65 | } 66 | }); 67 | mFpsText = (TextView) rootView.findViewById(R.id.tv_fps); 68 | mAnim1 = (SimpleAnimatedView) rootView.findViewById(R.id.sav1); 69 | mAnim1.setFpsListener(this); 70 | mAnim2 = (SimpleAnimatedView) rootView.findViewById(R.id.sav2); 71 | mAnim2.setFpsListener(this); 72 | mAnim3 = (SimpleAnimatedView) rootView.findViewById(R.id.sav3); 73 | mAnim3.setFpsListener(this); 74 | nextSmell(0); 75 | return rootView; 76 | } 77 | 78 | private void nextSmell(int index) { 79 | mAnim1.setVisibility(View.GONE); 80 | mAnim2.setVisibility(View.GONE); 81 | mAnim3.setVisibility(View.GONE); 82 | View anim; 83 | switch (index) { 84 | case 1: 85 | anim = mAnim1; 86 | break; 87 | case 2: 88 | anim = mAnim2; 89 | break; 90 | case 3: 91 | default: 92 | anim = mAnim3; 93 | break; 94 | } 95 | anim.setVisibility(View.VISIBLE); 96 | } 97 | 98 | @Override 99 | public void onFpsChange(float fps) { 100 | mFps = fps; 101 | } 102 | 103 | @Override 104 | public void onAttach(Activity activity) { 105 | super.onAttach(activity); 106 | mHandler.post(mFpsRunnable); 107 | } 108 | 109 | @Override 110 | public void onDetach() { 111 | super.onDetach(); 112 | mHandler.removeCallbacks(mFpsRunnable); 113 | } 114 | 115 | } -------------------------------------------------------------------------------- /res/layout/fr_fonts.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 16 | 17 | 21 | 22 | 27 | 28 | 33 | 34 | 39 | 40 | 45 | 46 | 51 | 52 | 57 | 58 | 63 | 64 | 69 | 70 | 75 | 76 | 81 | 82 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest; 2 | 3 | import android.app.ActionBar; 4 | import android.os.Bundle; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v4.app.FragmentActivity; 7 | import android.view.Menu; 8 | import android.widget.ArrayAdapter; 9 | 10 | import com.pixplicity.devfest.fragments.CodeSmellsFragment; 11 | import com.pixplicity.devfest.fragments.DrawingFragment; 12 | import com.pixplicity.devfest.fragments.Fonts1Fragment; 13 | import com.pixplicity.devfest.fragments.Fonts2Fragment; 14 | import com.pixplicity.devfest.fragments.SimpleAnimatedViewFragment; 15 | import com.pixplicity.devfest.fragments.StandardFragment; 16 | import com.pixplicity.mobdevcon.R; 17 | 18 | public class MainActivity extends FragmentActivity implements 19 | ActionBar.OnNavigationListener { 20 | 21 | /** 22 | * The serialization (saved instance state) Bundle key representing the 23 | * current dropdown position. 24 | */ 25 | private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item"; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.ac_main); 31 | 32 | // Set up the action bar to show a dropdown list. 33 | final ActionBar actionBar = getActionBar(); 34 | actionBar.setDisplayShowTitleEnabled(false); 35 | actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); 36 | 37 | // Set up the dropdown list navigation in the action bar. 38 | actionBar.setListNavigationCallbacks( 39 | // Specify a SpinnerAdapter to populate the dropdown list. 40 | new ArrayAdapter(actionBar.getThemedContext(), 41 | android.R.layout.simple_list_item_1, 42 | android.R.id.text1, new String[] { 43 | getString(R.string.title_section1), 44 | getString(R.string.title_section2), 45 | getString(R.string.title_section3), 46 | getString(R.string.title_section4), 47 | getString(R.string.title_section5), 48 | getString(R.string.title_section6), }), this); 49 | } 50 | 51 | @Override 52 | public void onRestoreInstanceState(Bundle savedInstanceState) { 53 | // Restore the previously serialized current dropdown position. 54 | if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) { 55 | getActionBar().setSelectedNavigationItem( 56 | savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM)); 57 | } 58 | } 59 | 60 | @Override 61 | public void onSaveInstanceState(Bundle outState) { 62 | // Serialize the current dropdown position. 63 | outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar() 64 | .getSelectedNavigationIndex()); 65 | } 66 | 67 | @Override 68 | public boolean onCreateOptionsMenu(Menu menu) { 69 | // Inflate the menu; this adds items to the action bar if it is present. 70 | // getMenuInflater().inflate(R.menu.main, menu); 71 | return true; 72 | } 73 | 74 | @Override 75 | public boolean onNavigationItemSelected(int position, long id) { 76 | // When the given dropdown item is selected, show its contents in the 77 | // container view. 78 | Fragment fragment = null; 79 | Bundle args = new Bundle(); 80 | switch (position) { 81 | case 0: 82 | fragment = new StandardFragment(); 83 | break; 84 | case 1: 85 | fragment = new Fonts1Fragment(); 86 | break; 87 | case 2: 88 | fragment = new Fonts2Fragment(); 89 | break; 90 | case 3: 91 | fragment = new SimpleAnimatedViewFragment(); 92 | break; 93 | case 4: 94 | fragment = new CodeSmellsFragment(); 95 | break; 96 | case 5: 97 | fragment = new DrawingFragment(); 98 | break; 99 | } 100 | if (fragment == null) { 101 | return false; 102 | } 103 | fragment.setArguments(args); 104 | getSupportFragmentManager().beginTransaction() 105 | .replace(R.id.container, fragment).commit(); 106 | return true; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Custom components 5 | Settings 6 | Hello world! 7 | Components 8 | Standard components 9 | Custom fonts 10 | Custom fonts (styled) 11 | Simple animation 12 | Code smells 13 | Drawing 14 | 15 | Send 16 | A very bad quack might jinx zippy fowls. 17 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin vitae lorem ut purus vehicula condimentum. Nam vestibulum rhoncus neque, eu vehicula libero fringilla vitae. Aliquam quis velit ligula. Praesent feugiat tellus et nunc commodo non tincidunt purus interdum. Aliquam venenatis venenatis tempor. Nulla enim orci, adipiscing posuere tincidunt vel, ultrices non felis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nulla nulla, adipiscing imperdiet interdum id, tristique eu neque. Praesent eleifend aliquam erat, nec elementum enim lacinia quis. Phasellus lobortis purus sed neque molestie bibendum. Sed magna tellus, convallis non pulvinar nec, eleifend non tellus. Duis condimentum nisi non ante consectetur ornare egestas quis turpis. Phasellus placerat, neque id pharetra vestibulum, velit turpis ornare lacus, nec lacinia ligula quam id felis. Nam sed nisi lacus. Nulla eu turpis justo. In vitae enim non sem facilisis congue at at diam. 18 | Maecenas venenatis venenatis sem, euismod rutrum massa rhoncus nec. Quisque velit dolor, lobortis eu scelerisque ac, porta eu eros. Ut tincidunt sollicitudin purus at cursus. Praesent hendrerit ullamcorper justo, a vulputate orci aliquet scelerisque. Curabitur dignissim neque id purus congue faucibus. Duis luctus dictum mi, non blandit justo pellentesque vehicula. Nullam placerat nisl a dui facilisis accumsan. Maecenas volutpat feugiat enim posuere consectetur. Aenean adipiscing leo ac nibh cursus molestie. Quisque consequat hendrerit elementum. 19 | Nulla facilisi. Fusce ac varius nisl. Maecenas a iaculis tortor. Morbi porttitor diam id neque convallis sit amet rutrum massa ultricies. Quisque id orci et turpis accumsan lobortis sed eu neque. Aliquam non mattis dolor. Suspendisse facilisis pulvinar enim nec aliquet. Nam vulputate dolor mi. Vivamus adipiscing lectus quis est lacinia sed rhoncus mauris tincidunt. Curabitur posuere metus sit amet nulla euismod porttitor. Duis rhoncus bibendum mauris fringilla vehicula. Mauris interdum, lectus eu elementum dictum, purus ligula malesuada nibh, eu mollis odio tortor at ligula. Nulla dictum ligula eu odio ornare vitae iaculis purus tincidunt. In hac habitasse platea dictumst. Nam felis sapien, auctor ornare volutpat non, posuere in massa. 20 | Vivamus suscipit hendrerit nisl at malesuada. In hac habitasse platea dictumst. Aenean at mi tellus. Vestibulum adipiscing tortor id ligula sagittis dictum luctus sed mauris. Duis ligula nibh, commodo vitae faucibus eu, sagittis et justo. Praesent suscipit felis eget mi cursus placerat. Nullam et odio urna, eu porta enim. Ut dui neque, cursus ac egestas vitae, laoreet sit amet tellus. Ut dapibus tincidunt erat, nec lobortis dolor porttitor sed. 21 | In mi nunc, pellentesque nec ullamcorper sed, tincidunt id sapien. Praesent consectetur pharetra elit. Integer placerat nisl ut elit ullamcorper sed faucibus lectus hendrerit. In scelerisque justo vel est vestibulum eleifend. Maecenas dolor mi, sollicitudin vitae elementum ut, mollis eget lorem. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris vitae ligula turpis. Morbi condimentum consectetur arcu id tristique. Maecenas leo eros, gravida et ultricies in, euismod eget mi. 22 | 23 | -------------------------------------------------------------------------------- /src/com/pixplicity/devfest/widgets/SimpleAnimatedView.java: -------------------------------------------------------------------------------- 1 | package com.pixplicity.devfest.widgets; 2 | 3 | import java.util.Iterator; 4 | import java.util.Stack; 5 | 6 | import android.annotation.TargetApi; 7 | import android.content.Context; 8 | import android.graphics.Canvas; 9 | import android.graphics.Color; 10 | import android.graphics.Paint; 11 | import android.graphics.RectF; 12 | import android.os.Build; 13 | import android.util.AttributeSet; 14 | import android.view.View; 15 | 16 | public class SimpleAnimatedView extends View { 17 | 18 | public static interface FpsListener { 19 | 20 | public abstract void onFpsChange(float fps); 21 | 22 | } 23 | 24 | protected static final long FPS_DELAY = 1000 / 60; 25 | 26 | protected float mRadius = 200; 27 | protected float mAngleStart, mAngleEnd; 28 | protected RectF mRect = new RectF(0, 0, mRadius, mRadius); 29 | protected Paint mPaintFg = new Paint(Paint.ANTI_ALIAS_FLAG); 30 | protected Paint mPaintLn = new Paint(Paint.ANTI_ALIAS_FLAG); 31 | protected Paint mPaintBg = new Paint(Paint.ANTI_ALIAS_FLAG); 32 | 33 | protected final Runnable animator = new Runnable() { 34 | 35 | @Override 36 | public void run() { 37 | if (mAngleEnd <= 360) { 38 | mAngleEnd += 1f; 39 | } else if (mAngleStart <= 360) { 40 | mAngleStart += 1f; 41 | } else { 42 | resetAnimation(); 43 | } 44 | nextFrame(); 45 | invalidate(); 46 | } 47 | }; 48 | 49 | private long lastTime; 50 | private Stack fpsList = new Stack(); 51 | private FpsListener fpsListener; 52 | 53 | public SimpleAnimatedView(Context context, AttributeSet attrs) { 54 | super(context, attrs); 55 | createPaints(); 56 | resetAnimation(); 57 | } 58 | 59 | protected void createPaints() { 60 | mPaintBg.setStyle(Paint.Style.FILL); 61 | mPaintBg.setColor(Color.argb(128, 233, 233, 233)); 62 | mPaintLn.setStyle(Paint.Style.STROKE); 63 | mPaintLn.setColor(Color.argb(128, 187, 187, 187)); 64 | mPaintLn.setStrokeWidth(2); 65 | mPaintFg.setStyle(Paint.Style.FILL); 66 | mPaintFg.setColor(Color.argb(255, 0, 153, 204)); 67 | } 68 | 69 | @Override 70 | protected void onAttachedToWindow() { 71 | super.onAttachedToWindow(); 72 | startAnimation(); 73 | } 74 | 75 | @Override 76 | protected void onDetachedFromWindow() { 77 | super.onDetachedFromWindow(); 78 | stopAnimation(); 79 | } 80 | 81 | @Override 82 | public void setVisibility(int visibility) { 83 | super.setVisibility(visibility); 84 | switch (visibility) { 85 | case View.VISIBLE: 86 | startAnimation(); 87 | break; 88 | default: 89 | stopAnimation(); 90 | break; 91 | } 92 | } 93 | 94 | @Override 95 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 96 | // Determine horizontal and vertical padding 97 | int paddingX = getPaddingLeft() + getPaddingRight(); 98 | int paddingY = getPaddingBottom() + getPaddingTop(); 99 | 100 | int minW, minH, w, h; 101 | switch (MeasureSpec.getMode(heightMeasureSpec)) { 102 | case MeasureSpec.EXACTLY: 103 | // Try for a height based on our minimum including vertical padding 104 | minH = getSuggestedMinimumHeight() + paddingY; 105 | h = MeasureSpec.getSize(heightMeasureSpec); 106 | 107 | // Set the width according to the height as our control should be 108 | // square, again compensating for padding 109 | minW = MeasureSpec.getSize(h) - paddingY + paddingX; 110 | w = resolveSize(minW, widthMeasureSpec); 111 | break; 112 | default: 113 | // Try for a width based on our minimum including horizontal padding 114 | minW = getSuggestedMinimumWidth() + paddingX; 115 | w = resolveSize(minW, widthMeasureSpec); 116 | 117 | // Set the height according to the width as our control should be 118 | // square, again compensating for padding 119 | minH = MeasureSpec.getSize(w) - paddingX + paddingY; 120 | h = resolveSize(minH, heightMeasureSpec); 121 | break; 122 | } 123 | 124 | setMeasuredDimension(w, h); 125 | } 126 | 127 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 128 | protected void nextFrame() { 129 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 130 | postDelayed(animator, FPS_DELAY); 131 | } else { 132 | postOnAnimation(animator); 133 | } 134 | } 135 | 136 | @Override 137 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 138 | super.onSizeChanged(w, h, oldw, oldh); 139 | // Account for padding 140 | mRect.left = getPaddingLeft(); 141 | mRect.top = getPaddingTop(); 142 | float diameter = Math.min( 143 | w - mRect.left - getPaddingRight(), 144 | h - mRect.top - getPaddingBottom()); 145 | mRect.right = mRect.left + diameter; 146 | mRect.bottom = mRect.top + diameter; 147 | mRadius = diameter / 2; 148 | } 149 | 150 | @Override 151 | protected void onDraw(Canvas canvas) { 152 | super.onDraw(canvas); 153 | canvas.drawCircle(mRect.left + mRadius, 154 | mRect.top + mRadius, 155 | mRadius, 156 | mPaintBg); 157 | canvas.drawCircle(mRect.left + mRadius, 158 | mRect.top + mRadius, 159 | mRadius, 160 | mPaintLn); 161 | canvas.drawArc(mRect, 162 | mAngleStart, 163 | mAngleEnd - mAngleStart, 164 | true, 165 | mPaintFg); 166 | if (fpsListener != null) { 167 | long duration = System.currentTimeMillis() - lastTime; 168 | lastTime = System.currentTimeMillis(); 169 | float fps = 1000f / duration; 170 | while (fpsList.size() > 10) { 171 | fpsList.pop(); 172 | } 173 | fpsList.push(fps); 174 | Iterator iter = fpsList.iterator(); 175 | fps = 0; 176 | while (iter.hasNext()) { 177 | fps += iter.next(); 178 | } 179 | fps /= fpsList.size(); 180 | fpsListener.onFpsChange(fps); 181 | } 182 | } 183 | 184 | protected void resetAnimation() { 185 | mAngleStart = mAngleEnd = 0; 186 | } 187 | 188 | private void startAnimation() { 189 | if (isShown()) { 190 | nextFrame(); 191 | } 192 | } 193 | 194 | private void stopAnimation() { 195 | removeCallbacks(animator); 196 | } 197 | 198 | public void setFpsListener(FpsListener listener) { 199 | fpsListener = listener; 200 | } 201 | 202 | } 203 | -------------------------------------------------------------------------------- /res/layout/fr_standard.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 15 | 21 | 22 |