【Android进阶】天天动听 悬浮歌词(迷你歌词)效果解读

天天动听, 这款Android手机上的音乐播放器,相信不少朋友都曾用过。 不知大家是否注意到,天天动听有一个迷你歌词的特效。

什么效果呢? 就是不管你切到什么画面, 歌词永远显示,并且可以拖动。 类型QQ音乐,在电脑上播放时显示的歌词效果。

下面先来看一下效果。

这个歌词是在所有界面之上的。

下面我们将这个效果解剖一下, 我认为主要有三个难点:

1.  歌词悬浮在所有页面之上

2.  歌词可以拖动位置

3.  歌词的播放效果 (颜色覆盖)

对于第一点,首先想到的就是 WindowManager , 这个类可能不少人都用过, 一般用于获取屏幕宽度、高度,那么这次就要利用这个类来让我们的歌词永远置顶。

通过查看API,我们看到,在WindowManager.LayoutParams类中,有好几个属性可以设置View置顶。

TYPE_SYSTEM_OVERLAY

Window type: system overlay windows, which need to be displayed on top of everything else.

TYPE_SYSTEM_ALERT

Window type: system window, such as low power alert.

TYPE_PHONE

These windows are normally placed above all applications, but behind the status bar.


下面我们来测试一下, 通过下面几句代码,就可以让一个View凌驾在所有View之上。

[java] view plaincopyprint?
  1. WindowManager wm = (WindowManager)getApplicationContext().getSystemService(WINDOW_SERVICE);
  2. WindowManager.LayoutParams params = new WindowManager.LayoutParams();
  3. params.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
  4. params.width = WindowManager.LayoutParams.WRAP_CONTENT;
  5. params.height = WindowManager.LayoutParams.WRAP_CONTENT;
  6. TextView tv = new TextView(this);
  7. wm.addView(tv, params);

WindowManager wm = (WindowManager)getApplicationContext().getSystemService(WINDOW_SERVICE); WindowManager.LayoutParams params = new WindowManager.LayoutParams(); params.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.height = WindowManager.LayoutParams.WRAP_CONTENT; TextView tv = new TextView(this); wm.addView(tv, params);


这边需要注意的是, WindowManager也是通过 getSystemService 来获取,但必须先 getApplicationContext, 否则就无效了。

直接WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE);  这样是无效的 !!

还有一点就是,别忘了在Manifest.xml中添加权限:

[xhtml] view plaincopyprint?
  1. <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

现在我们这样做,我们已经可以让歌词永远置顶了。 但是不要得意,现在这样,结果是我们TextView在最顶层了, 然后你就会发现,页面上什么操作都不能做了, 在TextView下面的任何东西,你都点不了。

为了解决这个,我们必须加上flags参数,让当前的View失去焦点,从而让后面的页面获得焦点。代码如下:

[java] view plaincopyprint?
  1. params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;

params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;

加上这一句就可以了。

好了,下面要处理的,就是让歌词可以移动。应该如何做呢?

我们知道,想要让一个View对象在页面上可以移动,只要实现其onTouchEvent事件即可。


下面开始实现第二步: 歌词移动!

首先我们自定义一个TextView类:MyTextView, 该类继承自TextView, 并实现其中的onTouchEvent方法,来看一下代码:

[java] view plaincopyprint?
  1. @Override
  2. public boolean onTouchEvent(MotionEvent event) {
  3. //触摸点相对于屏幕左上角坐标
  4. x = event.getRawX();
  5. y = event.getRawY() - TOOL_BAR_HIGH;
  6. Log.d(TAG, "------X: "+ x +"------Y:" + y);
  7. switch(event.getAction()) {
  8. case MotionEvent.ACTION_DOWN:
  9. startX = event.getX();
  10. startY = event.getY();
  11. break;
  12. case MotionEvent.ACTION_MOVE:
  13. updatePosition();
  14. break;
  15. case MotionEvent.ACTION_UP:
  16. updatePosition();
  17. startX = startY = 0;
  18. break;
  19. }
  20. return true;
  21. }
  22. //更新浮动窗口位置参数
  23. private void updatePosition(){
  24. // View的当前位置
  25. params.x = (int)( x - startX);
  26. params.y = (int) (y - startY);
  27. wm.updateViewLayout(this, params);
  28. }

@Override public boolean onTouchEvent(MotionEvent event) { //触摸点相对于屏幕左上角坐标 x = event.getRawX(); y = event.getRawY() - TOOL_BAR_HIGH; Log.d(TAG, "------X: "+ x +"------Y:" + y); switch(event.getAction()) { case MotionEvent.ACTION_DOWN: startX = event.getX(); startY = event.getY(); break; case MotionEvent.ACTION_MOVE: updatePosition(); break; case MotionEvent.ACTION_UP: updatePosition(); startX = startY = 0; break; } return true; } //更新浮动窗口位置参数 private void updatePosition(){ // View的当前位置 params.x = (int)( x - startX); params.y = (int) (y - startY); wm.updateViewLayout(this, params); }

其中getRawX、getRawY用于获取触摸点离屏幕左上角的距离。 而getX、getY用于获取触摸点离textView左上角的距离.

两者相减,就是View左上角的坐标了。

另外需要注意的是,在显示View这个View的时候,需要正确指定View的x,y坐标,否则拖动时会错位。

[java] view plaincopyprint?
  1. WindowManager wm = (WindowManager)getApplicationContext().getSystemService(WINDOW_SERVICE);
  2. WindowManager.LayoutParams params = MyTextView.params;
  3. params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
  4. params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
  5. params.width = WindowManager.LayoutParams.FILL_PARENT;
  6. params.height = WindowManager.LayoutParams.WRAP_CONTENT;
  7. params.alpha = 80;
  8. params.gravity=Gravity.LEFT|Gravity.TOP;
  9. //以屏幕左上角为原点,设置x、y初始值
  10. params.x = 0;
  11. params.y = 0;
  12. tv = new MyTextView(TopFrame.this);
  13. wm.addView(tv, params);

WindowManager wm = (WindowManager)getApplicationContext().getSystemService(WINDOW_SERVICE); WindowManager.LayoutParams params = MyTextView.params; params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE; params.width = WindowManager.LayoutParams.FILL_PARENT; params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.alpha = 80; params.gravity=Gravity.LEFT|Gravity.TOP; //以屏幕左上角为原点,设置x、y初始值 params.x = 0; params.y = 0; tv = new MyTextView(TopFrame.this); wm.addView(tv, params);

其中下面三句是关键:

[java] view plaincopyprint?
  1. params.gravity=Gravity.LEFT|Gravity.TOP;
  2. //以屏幕左上角为原点,设置x、y初始值
  3. params.x = 0;
  4. params.y = 0;

params.gravity=Gravity.LEFT|Gravity.TOP; //以屏幕左上角为原点,设置x、y初始值 params.x = 0; params.y = 0;

现在这样的话,就可以实现View的移动了。


下面实现第三步: 歌词的播放效果。

那么本例仅仅做一个循环, 实际音乐播放器要复杂些,需要根据歌剧的长度及时间间隔,来计算歌词的覆盖速度, 再根据这个速度来覆盖歌词,呈现给用户。

要实现歌词播放的效果,需要用到画笔Paint, 还要用到Shader, 还有一个就是UI刷新的问题。

一起来看下代码:

[java] view plaincopyprint?
  1. @Override
  2. protected void onDraw(Canvas canvas) {
  3. // TODO Auto-generated method stub
  4. super.onDraw(canvas);
  5. float1 += 0.001f;
  6. float2 += 0.001f;
  7. if(float2 > 1.0){
  8. float1 = 0.0f;
  9. float2 = 0.01f;
  10. }
  11. this.setText("");
  12. float len = this.getTextSize() * text.length();
  13. Shader shader = new LinearGradient(0, 0, len, 0,
  14. new int[] { Color.YELLOW, Color.RED },  new float[]{float1, float2},
  15. TileMode.CLAMP);
  16. Paint p = new Paint();
  17. p.setShader(shader);
  18. // 下面这句才控制歌词大小
  19. p.setTextSize(20f);
  20. p.setTypeface(Typeface.DEFAULT_BOLD);
  21. //此处x,y坐标也要注意,尤其是y坐标,要与字体大小协调
  22. canvas.drawText(text, 0, 20, p);
  23. }

@Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); float1 += 0.001f; float2 += 0.001f; if(float2 > 1.0){ float1 = 0.0f; float2 = 0.01f; } this.setText(""); float len = this.getTextSize() * text.length(); Shader shader = new LinearGradient(0, 0, len, 0, new int[] { Color.YELLOW, Color.RED }, new float[]{float1, float2}, TileMode.CLAMP); Paint p = new Paint(); p.setShader(shader); // 下面这句才控制歌词大小 p.setTextSize(20f); p.setTypeface(Typeface.DEFAULT_BOLD); //此处x,y坐标也要注意,尤其是y坐标,要与字体大小协调 canvas.drawText(text, 0, 20, p); }

好了,下面发一下效果图:


最后附上整个工程的代码:(一个就两个类,一个布局文件)

AndroidManifest.xml

[xhtml] view plaincopyprint?
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.yfz"
  4. android:versionCode="1"
  5. android:versionName="1.0">
  6. <application android:icon="@drawable/icon" android:label="@string/app_name">
  7. <activity android:name=".TopFrame"
  8. android:label="@string/app_name">
  9. <intent-filter>
  10. <action android:name="android.intent.action.MAIN" />
  11. <category android:name="android.intent.category.LAUNCHER" />
  12. </intent-filter>
  13. </activity>
  14. </application>
  15. <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
  16. <uses-sdk android:minSdkVersion="8"></uses-sdk>
  17. </manifest>

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.yfz" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".TopFrame" 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> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <uses-sdk android:minSdkVersion="8"></uses-sdk> </manifest>

main.xml

[java] view plaincopyprint?
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. >
  7. <Button
  8. android:id="@+id/bt"
  9. android:text=" 点我试试"
  10. android:layout_width = "wrap_content"
  11. android:layout_height="wrap_content"
  12. android:layout_gravity="center"
  13. />
  14. </LinearLayout>

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/bt" android:text=" 点我试试" android:layout_width = "wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> </LinearLayout>

TopFrame.java

[java] view plaincopyprint?
  1. package com.yfz;
  2. import com.yfz.view.MyTextView;
  3. import android.app.Activity;
  4. import android.graphics.Rect;
  5. import android.os.Bundle;
  6. import android.view.Gravity;
  7. import android.view.View;
  8. import android.view.WindowManager;
  9. import android.view.View.OnClickListener;
  10. import android.view.WindowManager.LayoutParams;
  11. import android.widget.Button;
  12. public class TopFrame extends Activity {
  13. /** Called when the activity is first created. */
  14. @Override
  15. public void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.main);
  18. Button button = (Button) findViewById(R.id.bt);
  19. button.setOnClickListener(onclick);
  20. }
  21. private MyTextView tv = null;
  22. OnClickListener onclick = new OnClickListener() {
  23. @Override
  24. public void onClick(View v) {
  25. if(tv != null && tv.isShown()){
  26. WindowManager wm = (WindowManager)getApplicationContext().getSystemService(TopFrame.this.WINDOW_SERVICE);
  27. wm.removeView(tv);
  28. }
  29. show();
  30. }
  31. };
  32. private void show(){
  33. Rect frame = new Rect();
  34. getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
  35. MyTextView.TOOL_BAR_HIGH = frame.top;
  36. WindowManager wm = (WindowManager)getApplicationContext().getSystemService(WINDOW_SERVICE);
  37. WindowManager.LayoutParams params = MyTextView.params;
  38. params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
  39. params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
  40. params.width = WindowManager.LayoutParams.FILL_PARENT;
  41. params.height = WindowManager.LayoutParams.WRAP_CONTENT;
  42. params.alpha = 80;
  43. params.gravity=Gravity.LEFT|Gravity.TOP;
  44. //以屏幕左上角为原点,设置x、y初始值
  45. params.x = 0;
  46. params.y = 0;
  47. tv = new MyTextView(TopFrame.this);
  48. wm.addView(tv, params);
  49. }
  50. @Override
  51. protected void onDestroy() {
  52. super.onDestroy();
  53. }
  54. }

package com.yfz; import com.yfz.view.MyTextView; import android.app.Activity; import android.graphics.Rect; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.WindowManager; import android.view.View.OnClickListener; import android.view.WindowManager.LayoutParams; import android.widget.Button; public class TopFrame extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button button = (Button) findViewById(R.id.bt); button.setOnClickListener(onclick); } private MyTextView tv = null; OnClickListener onclick = new OnClickListener() { @Override public void onClick(View v) { if(tv != null && tv.isShown()){ WindowManager wm = (WindowManager)getApplicationContext().getSystemService(TopFrame.this.WINDOW_SERVICE); wm.removeView(tv); } show(); } }; private void show(){ Rect frame = new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); MyTextView.TOOL_BAR_HIGH = frame.top; WindowManager wm = (WindowManager)getApplicationContext().getSystemService(WINDOW_SERVICE); WindowManager.LayoutParams params = MyTextView.params; params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE; params.width = WindowManager.LayoutParams.FILL_PARENT; params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.alpha = 80; params.gravity=Gravity.LEFT|Gravity.TOP; //以屏幕左上角为原点,设置x、y初始值 params.x = 0; params.y = 0; tv = new MyTextView(TopFrame.this); wm.addView(tv, params); } @Override protected void onDestroy() { super.onDestroy(); } }

MyTextView.java

[java] view plaincopyprint?
  1. package com.yfz.view;
  2. import android.content.Context;
  3. import android.graphics.Canvas;
  4. import android.graphics.Color;
  5. import android.graphics.LinearGradient;
  6. import android.graphics.Paint;
  7. import android.graphics.Rect;
  8. import android.graphics.Shader;
  9. import android.graphics.Typeface;
  10. import android.graphics.Shader.TileMode;
  11. import android.os.Handler;
  12. import android.os.Message;
  13. import android.util.Log;
  14. import android.view.MotionEvent;
  15. import android.view.View;
  16. import android.view.WindowManager;
  17. import android.widget.TextView;
  18. import android.widget.Toast;
  19. public class MyTextView extends TextView {
  20. private final String TAG = MyTextView.class.getSimpleName();
  21. public static int TOOL_BAR_HIGH = 0;
  22. public static WindowManager.LayoutParams params = new WindowManager.LayoutParams();
  23. private float startX;
  24. private float startY;
  25. private float x;
  26. private float y;
  27. private String text;
  28. WindowManager wm = (WindowManager)getContext().getApplicationContext().getSystemService(getContext().WINDOW_SERVICE);
  29. public MyTextView(Context context) {
  30. super(context);
  31. text = "世上只有妈妈好,有妈的孩子像块宝";
  32. this.setBackgroundColor(Color.argb(90, 150, 150, 150));
  33. // 下面这句话在此并不是控制歌词大小,仅仅是为了控制背景大小,如果不设置的话,Paint字体大时会被遮挡
  34. this.setTextSize(20f);
  35. handler = new Handler();
  36. handler.post(update);
  37. }
  38. @Override
  39. public boolean onTouchEvent(MotionEvent event) {
  40. //触摸点相对于屏幕左上角坐标
  41. x = event.getRawX();
  42. y = event.getRawY() - TOOL_BAR_HIGH;
  43. Log.d(TAG, "------X: "+ x +"------Y:" + y);
  44. switch(event.getAction()) {
  45. case MotionEvent.ACTION_DOWN:
  46. startX = event.getX();
  47. startY = event.getY();
  48. break;
  49. case MotionEvent.ACTION_MOVE:
  50. updatePosition();
  51. break;
  52. case MotionEvent.ACTION_UP:
  53. updatePosition();
  54. startX = startY = 0;
  55. break;
  56. }
  57. return true;
  58. }
  59. @Override
  60. protected void onDraw(Canvas canvas) {
  61. // TODO Auto-generated method stub
  62. super.onDraw(canvas);
  63. float1 += 0.001f;
  64. float2 += 0.001f;
  65. if(float2 > 1.0){
  66. float1 = 0.0f;
  67. float2 = 0.01f;
  68. }
  69. this.setText("");
  70. float len = this.getTextSize() * text.length();
  71. Shader shader = new LinearGradient(0, 0, len, 0,
  72. new int[] { Color.YELLOW, Color.RED },  new float[]{float1, float2},
  73. TileMode.CLAMP);
  74. Paint p = new Paint();
  75. p.setShader(shader);
  76. // 下面这句才控制歌词大小
  77. p.setTextSize(20f);
  78. p.setTypeface(Typeface.DEFAULT_BOLD);
  79. //此处x,y坐标也要注意,尤其是y坐标,要与字体大小协调
  80. canvas.drawText(text, 0, 20, p);
  81. }
  82. private Runnable update = new Runnable() {
  83. public void run() {
  84. MyTextView.this.update();
  85. handler.postDelayed(update, 3);
  86. }
  87. };
  88. private void update(){
  89. postInvalidate();
  90. }
  91. private float float1 = 0.0f;
  92. private float float2 = 0.01f;
  93. private Handler handler;
  94. //更新浮动窗口位置参数
  95. private void updatePosition(){
  96. // View的当前位置
  97. params.x = (int)( x - startX);
  98. params.y = (int) (y - startY);
  99. wm.updateViewLayout(this, params);
  100. }
  101. }

【Android进阶】天天动听 悬浮歌词相关推荐

  1. [Android实例] 天天动听 悬浮歌词(迷你歌词)效果解读

    天天动听, 这款Android手机上的音乐播放器,相信不少朋友都曾用过. 不知大家是否注意到,天天动听有一个迷你歌词的特效. 什么效果呢? 就是不管你切到什么画面, 歌词永远显示,并且可以拖动. 类型 ...

  2. 【Android进阶】天天动听 悬浮歌词(迷你歌词)效果解读

    天天动听, 这款Android手机上的音乐播放器,相信不少朋友都曾用过. 不知大家是否注意到,天天动听有一个迷你歌词的特效. 什么效果呢? 就是不管你切到什么画面, 歌词永远显示,并且可以拖动. 类型 ...

  3. 【Android进阶】天天动听 悬浮歌词 迷你歌词 效果解读

    天天动听, 这款Android手机上的音乐播放器,相信不少朋友都曾用过. 不知大家是否注意到,天天动听有一个迷你歌词的特效. 什么效果呢? 就是不管你切到什么画面, 歌词永远显示,并且可以拖动. 类型 ...

  4. android歌词效果,Android 天天动听 悬浮歌词(迷你歌词)效果解读

    天天动听, 这款Android手机上的音乐播放器,相信不少朋友都曾用过. 不知大家是否注意到,天天动听有一个迷你歌词的特效.什么效果呢? 就是不管你切到什么画面, 歌词永远显示,并且可以拖动. 类型Q ...

  5. Android 天天动听 悬浮歌词(迷你歌词)效果解读

    转自:http://mobile.51cto.com/android-266613.htm 天天动听, 这款Android手机上的音乐播放器,相信不少朋友都曾用过. 不知大家是否注意到,天天动听有一个 ...

  6. 【Android-悬浮窗】天天动听 悬浮歌词(迷你歌词)效果解读

    天天动听, 这款Android手机上的音乐播放器,相信不少朋友都曾用过. 不知大家是否注意到,天天动听有一个迷你歌词的特效. 什么效果呢? 就是不管你切到什么画面, 歌词永远显示,并且可以拖动. 类型 ...

  7. 天天动听悬浮歌词实现

    2019独角兽企业重金招聘Python工程师标准>>> 天天动听, 这款Android手机上的音乐播放器,相信不少朋友都曾用过. 不知大家是否注意到,天天动听有一个迷你歌词的特效. ...

  8. 天天动听 悬浮歌词(迷你歌词)效果解读

    2019独角兽企业重金招聘Python工程师标准>>> 先看效果图: 下面我们将这个效果解剖一下, 我认为主要有三个难点:1. 歌词悬浮在所有页面之上2. 歌词可以拖动位置3. 歌词 ...

  9. 天天动听 悬浮歌词(迷你歌词)效果解读 .

    原文地址:http://blog.csdn.net/feng88724/article/details/6362710

最新文章

  1. 用 mongodb + elasticsearch 实现中文检索
  2. linux c 删除 文件 第一行
  3. 2013-10-31 《October 31st, 2013》
  4. 笔记-信息系统开发基础-面向对象基本概念-多态
  5. strtok_r 和 strsep 使用实例
  6. win2008验证服务器错误,win2008dcdiag检测出的错误,求解决方法
  7. java 1.7 hashmap源码_jdk1.7hashMap源码分析
  8. python的内存泄露_Python 程序的内存泄露,教你一招来解决?
  9. 拳打苹果 脚踢三星 国产品牌占据泰国手机市场超半数份额!
  10. Linux 原来实现一个shell这么容易!(史上最简单详细)
  11. 跟我学SpringMVC目录汇总贴、PDF下载、源码下载
  12. 电子信息计算机调剂到能源动力,江苏科技大学机械、电子信息、电子信息能源动力、土木水利2020年考研调剂信息...
  13. 人工智能哪些技术在教育领域中得到了应用?
  14. 微信小程序-跟学笔记
  15. matlab利用geotiffread读取tif文件报错:‘错误使用 tifflib, 无法打开 TIFF 文件’
  16. 基础了解虚拟 DOM
  17. intel945显卡linux驱动,下载:Intel 945G/G965/G3X显卡新版驱动
  18. 使用lanyu的激活码,报错1653219,解决办法
  19. python字典怎么增加元素_Python字典(dict)增加元素
  20. 学习自旋电子学的笔记01:微磁模拟软件OOMMF的教程(中文版)7-7.3.4章

热门文章

  1. 996 ? 这次我想分享那些 955 的公司给你,面试的朋友看过来辣
  2. Spring异步调用传递Request对象问题分析
  3. 微信小程序设置页面背景颜色backgroundColor 无效的问题!
  4. 为什么禁用zeroconf_什么是Zeroconf?
  5. 云电脑用流量打游戏卡吗
  6. ros串口通讯接口编程
  7. 华为m3现在还能用吗_华为m3怎么样 值得买吗【图文】
  8. 如何将MP4视频文件转换成MP3音频格式
  9. DeepMind最新研究:“AI足球运动员”诞生,运球、抢断、传球、射门无所不能
  10. php遍历语句_php遍历是什么意思