Skip to content

Commit b859c96

Browse files
committed
Initial commit.
0 parents  commit b859c96

File tree

67 files changed

+2401
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+2401
-0
lines changed

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
*.iml
2+
.gradle
3+
/local.properties
4+
/.idea/workspace.xml
5+
/.idea/libraries
6+
.DS_Store
7+
/build
8+
/captures
9+
.externalNativeBuild
10+
/.idea/

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
![](images/icon.png)
2+
3+
HenCoder 绘制 6 属性动画 练习项目
4+
===
5+
6+
### 这是什么?
7+
8+
这不是一个独立使用的项目,它是 [HenCoder Android 开发进阶:UI 1-6 属性动画(上手篇)](http://hencoder.com/ui-1-6) 的配套练习项目。
9+
10+
### 怎么用?
11+
12+
项目是一个可以直接运行的 Android App 项目,项目运行后,在手机上打开是这样的:
13+
14+
![](images/preview.png)
15+
16+
工程下有一个 `/practice` 目录:
17+
18+
![](images/project_practice.png)
19+
20+
你要做的是就是,在 `/practice` 下的每一个 `PracticeXxxView.java` 文件中写代码,绘制出和页面上半部分相同的效果。就像这样:
21+
22+
![](images/preview_after.png)
23+
24+
> 当然,没必要做得和示例一毛一样。这是一个练习,而不是一个超级模仿秀,关键是把技能掌握。
25+
26+
如果做不出来,可以参考 `/sample` 目录下的代码:
27+
28+
![](images/project_sample.png)
29+
30+
练习做完,这期的内容也就掌握得差不多了。

app/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

app/build.gradle

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
apply plugin: 'com.android.application'
2+
3+
android {
4+
compileSdkVersion 25
5+
buildToolsVersion "25.0.3"
6+
defaultConfig {
7+
applicationId "com.hencoder.hencoderpracticedraw6"
8+
minSdkVersion 18
9+
targetSdkVersion 25
10+
versionCode 1
11+
versionName "1.0"
12+
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13+
}
14+
buildTypes {
15+
release {
16+
minifyEnabled false
17+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18+
}
19+
}
20+
}
21+
22+
dependencies {
23+
compile fileTree(include: ['*.jar'], dir: 'libs')
24+
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
25+
exclude group: 'com.android.support', module: 'support-annotations'
26+
})
27+
compile 'com.android.support:appcompat-v7:25.3.1'
28+
compile 'com.android.support.constraint:constraint-layout:1.0.2'
29+
compile 'com.android.support:support-core-ui:25.3.1'
30+
compile 'com.android.support:design:25.3.1'
31+
testCompile 'junit:junit:4.12'
32+
}

app/proguard-rules.pro

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Add project specific ProGuard rules here.
2+
# By default, the flags in this file are appended to flags specified
3+
# in /Users/rengwuxian/.android-sdk/tools/proguard/proguard-android.txt
4+
# You can edit the include path and order by changing the proguardFiles
5+
# directive in build.gradle.
6+
#
7+
# For more details, see
8+
# http://developer.android.com/guide/developing/tools/proguard.html
9+
10+
# Add any project specific keep options here:
11+
12+
# If your project uses WebView with JS, uncomment the following
13+
# and specify the fully qualified class name to the JavaScript interface
14+
# class:
15+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16+
# public *;
17+
#}
18+
19+
# Uncomment this to preserve the line number information for
20+
# debugging stack traces.
21+
#-keepattributes SourceFile,LineNumberTable
22+
23+
# If you keep the line number information, uncomment this to
24+
# hide the original source file name.
25+
#-renamesourcefileattribute SourceFile
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.hencoder.hencoderpracticedraw6;
2+
3+
import android.content.Context;
4+
import android.support.test.InstrumentationRegistry;
5+
import android.support.test.runner.AndroidJUnit4;
6+
7+
import org.junit.Test;
8+
import org.junit.runner.RunWith;
9+
10+
import static org.junit.Assert.*;
11+
12+
/**
13+
* Instrumentation test, which will execute on an Android device.
14+
*
15+
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
16+
*/
17+
@RunWith(AndroidJUnit4.class)
18+
public class ExampleInstrumentedTest {
19+
@Test
20+
public void useAppContext() throws Exception {
21+
// Context of the app under test.
22+
Context appContext = InstrumentationRegistry.getTargetContext();
23+
24+
assertEquals("com.hencoder.hencoderpracticedraw5", appContext.getPackageName());
25+
}
26+
}

app/src/main/AndroidManifest.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="com.hencoder.hencoderpracticedraw6">
4+
5+
<application
6+
android:allowBackup="true"
7+
android:icon="@mipmap/ic_launcher"
8+
android:label="@string/app_name"
9+
android:supportsRtl="true"
10+
android:theme="@style/AppTheme">
11+
<activity android:name="com.hencoder.hencoderpracticedraw6.MainActivity">
12+
<intent-filter>
13+
<action android:name="android.intent.action.MAIN" />
14+
15+
<category android:name="android.intent.category.LAUNCHER" />
16+
</intent-filter>
17+
</activity>
18+
</application>
19+
20+
</manifest>
46.8 KB
Binary file not shown.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package com.hencoder.hencoderpracticedraw6;
2+
3+
import android.os.Bundle;
4+
import android.support.annotation.LayoutRes;
5+
import android.support.annotation.StringRes;
6+
import android.support.design.widget.TabLayout;
7+
import android.support.v4.app.Fragment;
8+
import android.support.v4.app.FragmentPagerAdapter;
9+
import android.support.v4.view.ViewPager;
10+
import android.support.v7.app.AppCompatActivity;
11+
import android.view.Menu;
12+
13+
import java.util.ArrayList;
14+
import java.util.List;
15+
16+
public class MainActivity extends AppCompatActivity {
17+
TabLayout tabLayout;
18+
ViewPager pager;
19+
List<PageModel> pageModels = new ArrayList<>();
20+
21+
{
22+
pageModels.add(new PageModel(R.layout.sample_translation, R.string.title_translation, R.layout.practice_translation));
23+
pageModels.add(new PageModel(R.layout.sample_rotation, R.string.title_rotation, R.layout.practice_rotation));
24+
pageModels.add(new PageModel(R.layout.sample_scale, R.string.title_scale, R.layout.practice_scale));
25+
pageModels.add(new PageModel(R.layout.sample_alpha, R.string.title_alpha, R.layout.practice_alpha));
26+
pageModels.add(new PageModel(R.layout.sample_multi_properties, R.string.title_multi_properties, R.layout.practice_multi_properties));
27+
pageModels.add(new PageModel(R.layout.sample_duration, R.string.title_duration, R.layout.practice_duration));
28+
pageModels.add(new PageModel(R.layout.sample_interpolator, R.string.title_interpolator, R.layout.practice_interpolator));
29+
pageModels.add(new PageModel(R.layout.sample_object_anomator, R.string.title_object_animator, R.layout.practice_object_animator));
30+
}
31+
32+
@Override
33+
protected void onCreate(Bundle savedInstanceState) {
34+
super.onCreate(savedInstanceState);
35+
setContentView(R.layout.activity_main);
36+
37+
pager = (ViewPager) findViewById(R.id.pager);
38+
pager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
39+
40+
@Override
41+
public Fragment getItem(int position) {
42+
PageModel pageModel = pageModels.get(position);
43+
return PageFragment.newInstance(pageModel.sampleLayoutRes, pageModel.practiceLayoutRes);
44+
}
45+
46+
@Override
47+
public int getCount() {
48+
return pageModels.size();
49+
}
50+
51+
@Override
52+
public CharSequence getPageTitle(int position) {
53+
return getString(pageModels.get(position).titleRes);
54+
}
55+
});
56+
57+
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
58+
tabLayout.setupWithViewPager(pager);
59+
}
60+
61+
@Override
62+
public boolean onCreateOptionsMenu(Menu menu) {
63+
return super.onCreateOptionsMenu(menu);
64+
}
65+
66+
private class PageModel {
67+
@LayoutRes int sampleLayoutRes;
68+
@StringRes int titleRes;
69+
@LayoutRes int practiceLayoutRes;
70+
71+
PageModel(@LayoutRes int sampleLayoutRes, @StringRes int titleRes, @LayoutRes int practiceLayoutRes) {
72+
this.sampleLayoutRes = sampleLayoutRes;
73+
this.titleRes = titleRes;
74+
this.practiceLayoutRes = practiceLayoutRes;
75+
}
76+
}
77+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.hencoder.hencoderpracticedraw6;
2+
3+
import android.os.Bundle;
4+
import android.support.annotation.LayoutRes;
5+
import android.support.annotation.Nullable;
6+
import android.support.v4.app.Fragment;
7+
import android.view.LayoutInflater;
8+
import android.view.View;
9+
import android.view.ViewGroup;
10+
import android.view.ViewStub;
11+
12+
public class PageFragment extends Fragment {
13+
@LayoutRes int sampleLayoutRes;
14+
@LayoutRes int practiceLayoutRes;
15+
16+
public static PageFragment newInstance(@LayoutRes int sampleLayoutRes, @LayoutRes int practiceLayoutRes) {
17+
PageFragment fragment = new PageFragment();
18+
Bundle args = new Bundle();
19+
args.putInt("sampleLayoutRes", sampleLayoutRes);
20+
args.putInt("practiceLayoutRes", practiceLayoutRes);
21+
fragment.setArguments(args);
22+
return fragment;
23+
}
24+
25+
@Nullable
26+
@Override
27+
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
28+
View view = inflater.inflate(R.layout.fragment_page, container, false);
29+
30+
ViewStub sampleStub = (ViewStub) view.findViewById(R.id.sampleStub);
31+
sampleStub.setLayoutResource(sampleLayoutRes);
32+
sampleStub.inflate();
33+
34+
ViewStub practiceStub = (ViewStub) view.findViewById(R.id.practiceStub);
35+
practiceStub.setLayoutResource(practiceLayoutRes);
36+
practiceStub.inflate();
37+
38+
return view;
39+
}
40+
41+
@Override
42+
public void onCreate(@Nullable Bundle savedInstanceState) {
43+
super.onCreate(savedInstanceState);
44+
Bundle args = getArguments();
45+
if (args != null) {
46+
sampleLayoutRes = args.getInt("sampleLayoutRes");
47+
practiceLayoutRes = args.getInt("practiceLayoutRes");
48+
}
49+
}
50+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.hencoder.hencoderpracticedraw6;
2+
3+
import android.content.res.Resources;
4+
import android.util.DisplayMetrics;
5+
6+
public class Utils {
7+
public static float dpToPixel(float dp) {
8+
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
9+
return dp * metrics.density;
10+
}
11+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.hencoder.hencoderpracticedraw6.practice;
2+
3+
import android.content.Context;
4+
import android.graphics.Outline;
5+
import android.graphics.Path;
6+
import android.os.Build;
7+
import android.support.annotation.Nullable;
8+
import android.support.annotation.RequiresApi;
9+
import android.util.AttributeSet;
10+
import android.view.View;
11+
import android.view.ViewOutlineProvider;
12+
import android.widget.Button;
13+
import android.widget.ImageView;
14+
import android.widget.RelativeLayout;
15+
16+
import com.hencoder.hencoderpracticedraw6.R;
17+
18+
import static android.os.Build.VERSION.SDK_INT;
19+
import static com.hencoder.hencoderpracticedraw6.Utils.dpToPixel;
20+
21+
public class Practice01Translation extends RelativeLayout {
22+
Button animateBt;
23+
ImageView imageView;
24+
25+
public Practice01Translation(Context context) {
26+
super(context);
27+
}
28+
29+
public Practice01Translation(Context context, @Nullable AttributeSet attrs) {
30+
super(context, attrs);
31+
}
32+
33+
public Practice01Translation(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
34+
super(context, attrs, defStyleAttr);
35+
}
36+
37+
@Override
38+
protected void onAttachedToWindow() {
39+
super.onAttachedToWindow();
40+
41+
animateBt = (Button) findViewById(R.id.animateBt);
42+
imageView = (ImageView) findViewById(R.id.imageView);
43+
if (SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
44+
// 给音乐图标加上合适的阴影
45+
imageView.setOutlineProvider(new MusicOutlineProvider());
46+
}
47+
48+
animateBt.setOnClickListener(new OnClickListener() {
49+
@Override
50+
public void onClick(final View v) {
51+
// TODO 在这里处理点击事件,通过 View.animate().translationX/Y/Z() 来让 View 平移
52+
}
53+
});
54+
}
55+
56+
/**
57+
* 为音乐图标设置三角形的 Outline。
58+
*/
59+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
60+
class MusicOutlineProvider extends ViewOutlineProvider {
61+
Path path = new Path();
62+
63+
{
64+
path.moveTo(0, dpToPixel(10));
65+
path.lineTo(dpToPixel(7), dpToPixel(2));
66+
path.lineTo(dpToPixel(116), dpToPixel(58));
67+
path.lineTo(dpToPixel(116), dpToPixel(70));
68+
path.lineTo(dpToPixel(7), dpToPixel(128));
69+
path.lineTo(0, dpToPixel(120));
70+
path.close();
71+
}
72+
73+
@Override
74+
public void getOutline(View view, Outline outline) {
75+
outline.setConvexPath(path);
76+
}
77+
}
78+
}

0 commit comments

Comments
 (0)