一、前言

  马上就要520和521了,是不是还有像我一样的单身狗啊。我就知道有,所以这两天简单写了这个小程序(其实是替别人写的),虽然我并不会用去骗女孩子(因为最近太忙了,实习完之后要搞毕设,要搞论文啊,谁能帮帮我...),但是我想很多人肯定会感兴趣吧。如果你感兴趣就拿去逗妹子一乐吧。

  如果你很感兴趣,你可以在我写的基础上增辉加彩,或者根据我提供的资源自己动手,尝试一下。

二、先show一下效果

  

三、Android手机如何录制屏幕及转GIF

  https://www.aswifter.com/2015/07/10/android-record-video-to-gif/

  

  第一次试的时候没有成功,第二次设定屏幕分辨率后成功了,但是效果太差。果断又试了第三次,成功了,手机根目录出现了刚刚录制的视屏文件。

  adb pull 会把文件从手机上复制到本地(ANDROID_SDK_HOME/platform-tools目录下,也就是adb.exe所在的目录)

  接着就是转换成gif了,这里我用PS处理

  

    

   然后文件——》存储为web所有格式——》选择gif。如果gif过大,可能会导致ps崩溃,简单的做法就是调整图片的大小,就可以了。

四、下载地址

  apk文件:https://github.com/hjzgg/LoveDemo/tree/master/bin

  项目:https://github.com/hjzgg/LoveDemo

五、技术路线,分享我的制作过程

1.准备

  大二的时候搞过一段时间的android,时隔一年半,好多东西都忘了,不过现在捡起来也不晚。

  开发工具使用eclipse或者android studio。我使用的eclipse,那么就要自己去安装ADT和SDK了,安装的时间有点蛋疼啊。

2.资源收集

  作为一个表白程序,必须要有图片吧,文字吧, 最好加上背景音乐吧,不然就真的没有意思了。下面分享几个资源链接:

  文字特效: https://github.com/elevenetc/TextSurface

  图片切花特效: https://github.com/daimajia/AndroidImageSlider

  音乐播放器: http://www.cnblogs.com/TerryBlog/archive/2010/06/26/1765910.html

  

  先说一下文字特效,将文字特效的代码下载下来后,所有的演示代码放在了\app\src\main\java\su\levenetc\android\textsurface\sample\checks这里面,app\src\main\java\su\levenetc\android\textsurface\sample\SampleActivity.java是app入口activity。最主要的代码放在了library目录下,需要将library\src\main下面的文件复制到我们的项目中,参考入口activity的内容进行调用就可以了。 资源中提供了很多文字展示的效果,本人愚钝,只用了两个,而且用的不是太好。我主要增加了文字处理,效果结合的功能。将要展示的文字按照4句划分,然后调用文字效果展示。文字资源放在了assets文件夹下面。

  图片切换特效很好用,进本不要改动,直接把图片换了就行了,效果不错。

  音乐播放器引用网上的一位哥们儿的,写的简介靠谱,这里直接拿来用了,用的是MediaPlayer进行音乐播放。我改了一些地方,里面有点儿小bug。增加了一个功能,就是在sd卡不存在的时候(无论是内置的还是外置的),依然可以获取到音乐文件,考虑了好多方式,比如直接调用网上的,或者调用手机内存中的...,想了想还是将音乐文件放在项目当中了,可以放在res/raw下,也可以放在assets下,各有好处,本人放在了res/raw目录下。还有一个要注意的是判断手机的sd卡环境是否可以使用。具体的还是看代码吧。

3.主要代码

  说了这么多,最主要的代码都是在一个activity中,代码如下:

  MainActivity.java

public class MainActivity extends ListActivity implements BaseSliderView.OnSliderClickListener{

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //初始化图片切换
initChangePicture();
//初始化音乐
initMusic();
//初始化文字展示
initWord();
} @Override
public void onSliderClick(BaseSliderView slider) {
Toast.makeText(this, slider.getBundle().get("extra") + "",Toast.LENGTH_SHORT).show();
} private SliderLayout mDemoSlider;
private void initChangePicture(){
mDemoSlider = (SliderLayout)findViewById(R.id.slider); //两种方式加载数据 //加载本地
HashMap<String,String> url_maps = new HashMap<String, String>();
url_maps.put("GitOnWay", "http://gitonway.blog.163.com/"); //加载网络
HashMap<String,Integer> file_maps = new HashMap<String, Integer>();
file_maps.put("love-A",R.drawable.a);
file_maps.put("love-B",R.drawable.b);
file_maps.put("love-C",R.drawable.c);
file_maps.put("love-D", R.drawable.d); for(String name : file_maps.keySet()){
TextSliderView textSliderView = new TextSliderView(this);
// 初始化幻灯片页面
textSliderView
.description(name)
.image(file_maps.get(name))
.setOnSliderClickListener(this); //添加要传递的数据
textSliderView.getBundle()
.putString("extra",name); mDemoSlider.addSlider(textSliderView);
} // 幻灯片切换方式
mDemoSlider.setPresetTransformer(SliderLayout.Transformer.Accordion);
// 指示符位置
mDemoSlider.setPresetIndicator(SliderLayout.PresetIndicators.Center_Bottom);
// 定义指示器样式
// mDemoSlider.setCustomIndicator(your view);
// 幻灯片循环
// mDemoSlider.startAutoCycle();
// 停止循环
mDemoSlider.stopAutoCycle();
// 设置指示器的显示与否
mDemoSlider.setIndicatorVisibility(PagerIndicator.IndicatorVisibility.Visible);
// 设置幻灯片的转化时间
// mDemoSlider.setSliderTransformDuration(5000, null);
// 用来自定义幻灯片标题的显示方式
mDemoSlider.setCustomAnimation(new DescriptionAnimation());
// 幻灯片切换时间
mDemoSlider.setDuration(3000); // 实现随机切换
TimerTask task = new TimerTask() {
@Override
public void run() {
Transformer[] tranformers = SliderLayout.Transformer.values();
Transformer transformer = tranformers[(int) (Math.random() * tranformers.length)];
mDemoSlider.setPresetTransformer(transformer);
}
}; new Timer().schedule(task, 2000, 2000);
} //res/raw中的音乐文件资源映射
private Map<String, Integer> musicPath;
//播放对象
private MediaPlayer myMediaPlayer;
//播放列表
private List<String> myMusicList = new ArrayList<String>();
//当前播放歌曲的索引
private int currentListItem=0;
//音乐的路径, 如果存在sd卡,则使用sd卡,否则使用内存中的data目录
private static String MUSIC_PATH = hasSDCardMounted() ? new String(Environment.getExternalStorageDirectory().getAbsolutePath() + "/hjz/")
: null; private void initMusic(){
myMediaPlayer=new MediaPlayer();
findView();
musicList();
listener(); //自动播放第一首歌
if(myMusicList.size() > 0){
playMusic(MUSIC_PATH, myMusicList.get(currentListItem));
}
} public static boolean hasSDCardMounted() {
String state = Environment.getExternalStorageState();
if (state != null && state.equals(Environment.MEDIA_MOUNTED)) {
return true;
} else {
return false;
}
} //绑定音乐
private void musicList(){
try {
File home = new File(MUSIC_PATH);
//如果有sd卡,但是sd卡中没有指定的音乐文件夹,则采用项目中的音乐文件
if(MUSIC_PATH == null || home.listFiles() == null) {//绑定 res/raw下的音乐文件
MUSIC_PATH = null;
musicPath = new HashMap<String, Integer>();
musicPath.put("杨宗纬 - 一次就好.mp3", R.raw.yi_ci_jiu_hao);
musicPath.put("霍建华,赵丽颖 - 不可说.mp3", R.raw.bu_ke_shuo);
musicPath.put("川井憲次 - 孤独な巡礼.mp3", R.raw.gu_du_xun_li);
myMusicList.addAll(musicPath.keySet());
} else {
Log.v("MUSIC_PATH", MUSIC_PATH);
if(home.listFiles(new MusicFilter()).length>0){
for(File file:home.listFiles(new MusicFilter())){
myMusicList.add(file.getName());
}
}
}
if(myMusicList.size() > 0) {
ArrayAdapter<String> musicList = new ArrayAdapter<String>(MainActivity.this, R.layout.musicitme, myMusicList);
setListAdapter(musicList);
}
} catch (Exception e) {
Log.e("获取音乐文件出错:", e.toString());
}
} //获取按钮
void findView(){
viewHolder.start=(Button)findViewById(R.id.start);
viewHolder.stop=(Button)findViewById(R.id.stop);
viewHolder.next=(Button)findViewById(R.id.next);
viewHolder.pause=(Button)findViewById(R.id.pause);
viewHolder.last=(Button)findViewById(R.id.last);
} //监听事件
void listener(){
//停止
viewHolder.stop.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(myMediaPlayer.isPlaying()){
myMediaPlayer.reset();
}
}
});
//开始
viewHolder.start.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
if(myMusicList.size() == 0) return;
playMusic(MUSIC_PATH, myMusicList.get(currentListItem));
}
});
//下一首
viewHolder.next.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
nextMusic();
}
});
//暂停
viewHolder.pause.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
if(myMusicList.size() == 0) return;
if(myMediaPlayer.isPlaying()){
myMediaPlayer.pause();
}else{
myMediaPlayer.start();
}
}
});
//上一首
viewHolder.last.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
lastMusic();
}
}); } //播放音乐
void playMusic(String basePath, String path){
try {
if(basePath != null) {
myMediaPlayer.reset();
myMediaPlayer.setDataSource(basePath+path);
myMediaPlayer.prepare();
} else {
myMediaPlayer.pause();
myMediaPlayer.release();
myMediaPlayer = MediaPlayer.create(MainActivity.this, musicPath.get(path));
}
myMediaPlayer.start();
myMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
nextMusic();
}
});
} catch (Exception e) {
Log.e("播放sd卡音乐失败", e.toString());
e.printStackTrace();
}
} //下一首
void nextMusic(){
if(myMusicList.size() > 0) {
if(++currentListItem>=myMusicList.size()){
currentListItem=0;
}
playMusic(MUSIC_PATH, myMusicList.get(currentListItem));
}
} //上一首
void lastMusic(){
if(myMusicList.size() > 0) {
if(currentListItem!=0) {
playMusic(MUSIC_PATH, myMusicList.get(--currentListItem));
} else{
playMusic(MUSIC_PATH, myMusicList.get(currentListItem=myMusicList.size()-1));
}
}
} //当用户返回时结束音乐并释放音乐对象
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_BACK){
myMediaPlayer.stop();
myMediaPlayer.release();
this.finish();
return true;
}
return super.onKeyDown(keyCode, event);
} //当选择列表项时播放音乐
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
currentListItem=position;
playMusic(MUSIC_PATH, myMusicList.get(currentListItem));
} //初始化文字展示
private TextSurface textSurface;
private void initWord(){
LinearLayout layout = (LinearLayout) findViewById(R.id.LinearLayoutWord);//找到你要设透明背景的layout 的id
layout.getBackground().setAlpha(60);//0~255透明度值
textSurface = (TextSurface) findViewById(R.id.text_surface);
textSurface.postDelayed(new Runnable() {
@Override public void run() {
show();
}
}, 1000);
} private void show() {
textSurface.reset();
List<AnimationsSet> animationsSets = new ArrayList<AnimationsSet>();
animationsSets.add(CookieThumperSample.getCookieThumperAnimations(getAssets()));
animationsSets.addAll(SlideSample.getSlideAnimations(getContents()));
textSurface.play(TYPE.SEQUENTIAL, animationsSets.toArray(new AnimationsSet[]{})); // ColorSample.play(textSurface);
// AlignSample.play(textSurface);
// Rotation3DSample.play(textSurface);
// ScaleTextSample.run(textSurface);
// ShapeRevealLoopSample.play(textSurface);
// ShapeRevealSample.play(textSurface);
// SlideSample.play(textSurface);
// SurfaceScaleSample.play(textSurface);
// SurfaceTransSample.play(textSurface);
} private List<String> getContents(){
List<String> contents = new ArrayList<String>();
try{
//得到资源中的asset数据流
String fileName = "content.txt"; //文件名字
String res="";
InputStream in = getResources().getAssets().open(fileName);
int length = in.available();
byte [] buffer = new byte[length];
in.read(buffer);
in.close();
res = EncodingUtils.getString(buffer, "UTF-8");
String[] strings = res.split("[,|,|\\.|。]");
int len = strings.length/4 * 4;
for(int i=0; i < len; ++i)
contents.add(strings[i]);
}catch(Exception e){
e.printStackTrace();
Log.e("getContents", e.toString());
}
return contents;
}
}

  activity_main.xml(页面布局)

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.gitonway.androidimagesliderdemo.activity.MainActivity"> <LinearLayout android:id="@+id/LinearLayoutPicture"
android:orientation="vertical"
android:layout_weight="3"
android:layout_height="fill_parent"
android:layout_width="match_parent">
<!-- 图片切换 -->
<com.gitonway.androidimagesliderdemo.widget.imageslider.SliderLayout
android:id="@+id/slider"
android:layout_width="match_parent"
android:layout_height="fill_parent"
custom:pager_animation="Accordion"
custom:auto_cycle="true"
custom:indicator_visibility="visible"
custom:pager_animation_span="1100"/> <!-- <com.gitonway.androidimagesliderdemo.widget.imageslider.Indicators.PagerIndicator
android:id="@+id/custom_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
custom:selected_color="#0095BF"
custom:unselected_color="#55333333"
custom:selected_drawable="@drawable/ic_launcher"
custom:shape="oval"
custom:selected_padding_left="6dp"
custom:selected_padding_right="6dp"
custom:unselected_padding_left="2dp"
custom:unselected_padding_right="2dp"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
custom:selected_width="6dp"
custom:selected_height="6dp"
custom:unselected_width="6dp"
custom:unselected_height="6dp"
android:layout_marginBottom="20dp"
/>
<com.gitonway.androidimagesliderdemo.widget.imageslider.Indicators.PagerIndicator
android:id="@+id/custom_indicator2"
style="@style/AndroidImageSlider_Corner_Oval_Orange"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
/> -->
</LinearLayout> <!-- 文字展现 -->
<LinearLayout android:id="@+id/LinearLayoutWord"
android:layout_weight="3"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="@android:color/background_dark"
android:layout_width="match_parent"> <com.textsurface.TextSurface
android:id="@+id/text_surface"
android:layout_height="fill_parent"
android:layout_width="match_parent"/> </LinearLayout> <!-- 音乐播放器 --> <LinearLayout
android:id="@+id/LinearLayoutMusic"
android:layout_width="match_parent"
android:layout_weight="4"
android:layout_height="fill_parent"
android:orientation="vertical" > <ListView
android:id="@id/android:list"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="fill_parent"
android:scrollbars="vertical" /> <LinearLayout
android:id="@+id/bottomBtn"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center|center_horizontal|center_vertical"
android:orientation="horizontal" > <Button android:id="@+id/last"
android:background="@drawable/last"
android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:id="@+id/stop"
android:background="@drawable/stop"
android:layout_marginLeft="10dp"
android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:id="@+id/start"
android:background="@drawable/start"
android:layout_marginLeft="10dp"
android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:id="@+id/pause" android:layout_width="wrap_content"
android:background="@drawable/pause"
android:layout_marginLeft="10dp"
android:layout_height="wrap_content"></Button> <Button android:id="@+id/next"
android:background="@drawable/next"
android:layout_marginLeft="10dp"
android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
</LinearLayout>
</LinearLayout> </LinearLayout>

  

android表白app的更多相关文章

  1. 轻松搞定表白女朋友:Android版APP (零基础也可直接下载软件)

    在我们平时生活当中,经常会看到一些表白女朋友的html网页,但是Android端的表白软件可以说是基本没有,笔者在全网搜了一下,就没有一个可以用的.安卓端可以给人一种定制和精美的感觉,这是网页所做不到 ...

  2. 关于高校表白App的NABCD项目分析

    N(Need,需求) 首先,针对本校男多女少 的具体情况,为广大本校大学生提供一个更加宽广的平台: 其次,针对当前各高校均有校园表白墙的实际情况,各表白墙难以整合在一起,使得信息不够集中的现状,我们小 ...

  3. Cordova 打包 Android release app 过程详解

    Cordova 打包 Android release app 过程详解 时间 -- :: SegmentFault 原文 https://segmentfault.com/a/119000000517 ...

  4. 【Android端 APP GPU过度绘制】GPU过度绘制及优化

    一.Android端的卡顿 Android端APP在具体使用的过程中容易出现卡顿的情况,比如查看页面时出现一顿一顿的感受,切换tab之后响应很慢,或者具体滑动操作的时候也很慢. 二.卡顿的原因 卡顿的 ...

  5. 分享我开发的网络电话Android手机APP正式版,图文详解及下载

    分享我开发的网络电话Android手机APP正式版,图文详解及下载 分享我开发的网络电话Android手机APP正式版 实时语音通讯,可广域网实时通讯,音质清晰流畅! 安装之后的运行效果: 第一次安装 ...

  6. Android开发App工程结构搭建

    本文算是一篇漫谈,谈一谈关于android开发中工程初始化的时候如何在初期我们就能搭建一个好的架构.      关于android架构,因为手机的限制,目前我觉得也确实没什么大谈特谈的,但是从开发的角 ...

  7. Android 启动APP黑屏解决方案

    #Android 启动APP黑屏解决方案# 1.自定义Theme //1.设置背景图Theme <style name="Theme.AppStartLoad" parent ...

  8. Android手机app启动的时候第一个Activity必须是MainActivity吗

    原文:Android手机app启动的时候第一个Activity必须是MainActivity吗 Android手机APP启动的第一个Activity是可以自己设置的,不是必须的MainActivity ...

  9. Android原生APP内分享

    Android原生APP内分享,可实现数据分享以及assets文件夹分享及私有文件分享 项目地址:https://github.com/json-pu/AndroidAppShare.git

随机推荐

  1. js get browser vertion (js获取浏览器信息版本)

    1问题:js get browser vertion (js获取浏览器信息版本) 2解决方案 Copy this script into your JavaScript files. It works ...

  2. Eclipse 双击变量,其他相同变量有底色

    转载:http://blog.csdn.net/majian_1987/article/details/46691697 方便下次查找. 在Eclipse中,鼠标选中或者光标移动到Java类的变量名时 ...

  3. xcode8 升级后注释快键键不能使用的解决方法

    1.这个是因为苹果解决xcode ghost.把插件屏蔽了.解决方法 命令运行:  sudo /usr/libexec/xpccachectl 然后必须重启电脑后生效 2.option+command ...

  4. HashMap实现缓存(二)

    package com.cache; import java.util.*; //Description: 管理缓存 //可扩展的功能:当chche到内存溢出时必须清除掉最早期的一些缓存对象,这就要求 ...

  5. ubuntu14.04 安装 hadoop2.4.0

    转载:ubuntu搭建hadoop-Ver2.6.0完全分布式环境笔记 自己在搭建hadoop平台时,碰到一些困难,按照该博文解决了问题,转载一下,作为记录. 2 先决条件 确保在你集群中的每个节点上 ...

  6. 丰富“WinForms” 的一个别样"项目"(学生管理)

    一个别样的WinForms项目,他并没多么的新颖,但是它的用处确实有点多,或许会有你需要的地方:如果你对WinForms中那么多控件无法把握,又或者是你根本就不懂,那我觉得你应该好好看看,如果一个人的 ...

  7. Js函数的概念、作用、创建、调用!

    一.函数是用来帮助我们封装.调用代码的最方便的工具! 二.函数的创建方法有三种: 三.函数的创建方式有3种,调用方式也不是单一的,调用方式有4种!      1.作为一个函数去调用 函数名+();(函 ...

  8. 一个微软的DDD架构图

  9. Microsoft .NET Framework 4.0.3版下载

    适用于 Microsoft .NET Framework 4 的更新 4.0.3,其中包含一系列新增功能,用于满足高端客户的功能需求和重要 .NET Framework 方案的需求. http://w ...

  10. ABP理论学习之N层架构

    返回总目录 自从写这个系列博客之后,发现很多园友还是希望有个直接运行的demo,其实在github上就有官方的demo,我直接把这demo的链接放到这里吧,另外,我分析,这些找不到demo的同学,很可 ...