lottie开源库的诞生为我们动画的设置可谓提供了很大的便利,我们可以直接使用设计师用AE产生的json格式动画坐标,进行操作,简单快捷……
dependencies {
compile 'com.airbnb.android:lottie:1.0.3'
}
package cn.hnshangyu.lottie;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import java.util.ArrayList;
import butterknife.Bind;
import butterknife.ButterKnife;
import cn.hnshangyu.lottie.adapter.ViewPagerAdapter;
import cn.hnshangyu.lottie.fragment.PageFourFragment;
import cn.hnshangyu.lottie.fragment.PageOneFragment;
import cn.hnshangyu.lottie.fragment.PageThreeFragment;
import cn.hnshangyu.lottie.fragment.PageTwoFragment;
public class MainActivity extends AppCompatActivity {
@Bind(R.id.toolbar)
Toolbar toolbar;
@Bind(R.id.toolbar_tab)
TabLayout toolbarTab;
@Bind(R.id.appbar_layout)
AppBarLayout appbarLayout;
@Bind(R.id.viewpager)
ViewPager viewpager;
private Snackbar snackbar;
private static ArrayList fragmentList = new ArrayList<>();
private ViewPagerAdapter viewPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
// 用toolBar替换ActionBar
setToolBarReplaceActionBar();
//创建fragment
createFragment();
// 给viewpager设置适配器
setViewPagerAdapter();
//tablayout和viewpager建立联系
setTabBindViewPager();
}
/**
* 用toolBar替换ActionBar
*/
private void setToolBarReplaceActionBar() {
setSupportActionBar(toolbar);
//显示系统返回箭头
// getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationIcon(R.drawable.ic_back);
//去除系统标题
getSupportActionBar().setDisplayShowTitleEnabled(false);
toolbar.setTitle(" 黄晓果");
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
snackbar = Snackbar.make(view, "确定要退出程序吗?", Snackbar.LENGTH_INDEFINITE);
snackbar.setAction("退出", new View.OnClickListener() {
@Override
public void onClick(View view) {
MainActivity.this.finish();
}
}).show();
new Thread(new Runnable() {
@Override
public void run() {
SystemClock.sleep(3000);
if (snackbar != null && snackbar.isShown())
snackbar.dismiss();
}
}).start();
}
});
}
/**
* 创建fragment
*/
private void createFragment() {
fragmentList.add(PageOneFragment.newInstance("方式一"));
fragmentList.add(PageTwoFragment.newInstance("方式二"));
fragmentList.add(PageThreeFragment.newInstance("方式三"));
fragmentList.add(PageFourFragment.newInstance("方式四"));
}
/**
* 给viewpager设置适配器
*/
private void setViewPagerAdapter() {
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), fragmentList);
viewpager.setAdapter(viewPagerAdapter);
}
/**
* tablayout和viewpager建立联系
*/
private void setTabBindViewPager() {
//tablayout和viewpager建立联系方式一:tab与viewpager之间的相互绑定
// viewpager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(toolbarTab));
// toolbarTab.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewpager));
//tablayout和viewpager建立联系方式二: 使用此方法Tablayout中的TabItem设置icon无效
// (android:icon="@drawable/tab_selector" )只能使用 android:text="分享"
//并且在ViewPagerAdapter中必须重写getPageTitle方法,不然无效
toolbarTab.setupWithViewPager(viewpager);
}
}
效果一、lottie简单动画实现
1. 布局如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/animation_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" />
FrameLayout>
2. 实现动画播放:
package cn.hnshangyu.lottie.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.airbnb.lottie.LottieAnimationView;
import butterknife.Bind;
import butterknife.ButterKnife;
import cn.hnshangyu.lottie.R;
public class PageOneFragment extends Fragment {
public static final String ARG_PAGE = "MESSAGE";
@Bind(R.id.animation_view)
LottieAnimationView animationView;
private String mPage;
public static PageOneFragment newInstance(String message) {
Bundle args = new Bundle();
args.putString(ARG_PAGE, message);
PageOneFragment pageFragment = new PageOneFragment();
pageFragment.setArguments(args);
return pageFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage = getArguments().getString(ARG_PAGE);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_one_page, null);
ButterKnife.bind(this, view);
return view;
}
/**
* 播放动画
*/
@Override
public void onResume() {
super.onResume();
animationView.setProgress(0f);
//添加播放源 或app:lottie_fileName="Logo/LogoSmall.json"
animationView.setAnimation("Logo/LogoSmall.json");
//是否循环播放 或app:lottie_loop="true"
animationView.loop(true);
//开始播放 或app:lottie_autoPlay="true"
animationView.playAnimation();
}
/**
* 停止动画
*/
@Override
public void onPause() {
super.onPause();
animationView.cancelAnimation();
}
@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
}
}
效果二、动画播放的监听
1.布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/animation_view"
android:layout_width="200dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:layout_height="200dp" />
<Button
android:id="@+id/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="start" />
<Button
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_below="@id/start"
android:layout_centerInParent="true"
android:text="stop" />
RelativeLayout>
2.实现监听接口:
package cn.hnshangyu.lottie.fragment;
import android.animation.Animator;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.airbnb.lottie.LottieAnimationView;
import butterknife.Bind;
import butterknife.ButterKnife;
import cn.hnshangyu.lottie.R;
public class PageTwoFragment extends Fragment {
public static final String ARG_PAGE = "MESSAGE";
@Bind(R.id.animation_view)
LottieAnimationView animationView;
@Bind(R.id.start)
Button start;
@Bind(R.id.stop)
Button stop;
private String mPage;
private String[] JsonList = new String[]{"Mobilo/A.json", "Mobilo/B.json", "Mobilo/C.json", "Mobilo/D.json",
"Mobilo/E.json", "Mobilo/F.json", "Mobilo/G.json", "Mobilo/F.json", "Mobilo/I.json", "Mobilo/J.json", "Mobilo/K.json",
"Mobilo/L.json", "Mobilo/M.json", "Mobilo/N.json", "Mobilo/O.json", "Mobilo/P.json", "Mobilo/Q.json", "Mobilo/R.json",
"Mobilo/S.json", "Mobilo/T.json", "Mobilo/U.json", "Mobilo/V.json", "Mobilo/W.json", "Mobilo/X.json", "Mobilo/Y.json", "Mobilo/Z.json"};
public static PageTwoFragment newInstance(String message) {
Bundle args = new Bundle();
args.putString(ARG_PAGE, message);
PageTwoFragment pageFragment = new PageTwoFragment();
pageFragment.setArguments(args);
return pageFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage = getArguments().getString(ARG_PAGE);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_two_page, null);
ButterKnife.bind(this, view);
initListener();
return view;
}
private void initListener() {
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
animationView.removeAnimatorListener(myAnimatorListener);
animationPosition = 0;
startAnimation();
}
});
stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
animationPosition = JsonList.length + 1;
animationView.cancelAnimation();
}
});
}
private int animationPosition = 0;
/**
* 播放动画
*/
private void startAnimation() {
animationView.setProgress(0f);
//添加播放源
animationView.setAnimation(JsonList[animationPosition]);
//是否循环播放
animationView.loop(false);
//开始播放
animationView.playAnimation();
animationView.addAnimatorListener(myAnimatorListener);
}
private Animator.AnimatorListener myAnimatorListener = new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
Log.e("huangxiaoguo", "onAnimationStart");
//开始
animationPosition = animationPosition + 1;
}
@Override
public void onAnimationEnd(Animator animator) {
Log.e("huangxiaoguo", "onAnimationEnd");
//结束
if (animationPosition < JsonList.length) {
//添加播放源
animationView.setAnimation(JsonList[animationPosition]);
//是否循环播放
animationView.loop(false);
//开始播放
animationView.playAnimation();
} else if (animationPosition == JsonList.length) {
animationPosition = 0;
//添加播放源
animationView.setAnimation(JsonList[animationPosition]);
//是否循环播放
animationView.loop(false);
//开始播放
animationView.playAnimation();
}
}
@Override
public void onAnimationCancel(Animator animator) {
Log.e("huangxiaoguo", "onAnimationCancel");
//取消
}
@Override
public void onAnimationRepeat(Animator animator) {
Log.e("huangxiaoguo", "onAnimationRepeat");
//重复
}
};
/**
* 停止动画
*/
@Override
public void onPause() {
super.onPause();
animationPosition = JsonList.length + 1;
animationView.cancelAnimation();
}
@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
}
}
效果三、动画播放暂停,重新播放、循环播放等一系列设置
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/animation_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:duplicateParentState="true" />
<android.support.v7.widget.AppCompatSeekBar
android:id="@+id/seek_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="64dp"
android:layout_marginRight="64dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<ImageButton
android:id="@+id/restart"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:background="?selectableItemBackgroundBorderless"
android:src="@drawable/ic_restart" />
<ImageButton
android:id="@+id/play_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical"
android:layout_marginBottom="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginTop="12dp"
android:background="@drawable/play_button_background"
android:src="@drawable/ic_play_pause" />
<ImageButton
android:id="@+id/loop"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:background="?selectableItemBackgroundBorderless"
android:src="@drawable/ic_loop" />
LinearLayout>
LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_margin="20dp"
android:src="@drawable/ic_assets" />
RelativeLayout>
package cn.hnshangyu.lottie.fragment;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v7.widget.AppCompatSeekBar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.SeekBar;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.model.LottieComposition;
import butterknife.Bind;
import butterknife.ButterKnife;
import cn.hnshangyu.lottie.R;
public class PageThreeFragment extends Fragment implements View.OnClickListener {
public static final String ARG_PAGE = "MESSAGE";
public static final int GO_DISLOG = 212;
public static final String EXTRA_ANIMATION_NAME = "animation_name";
@Bind(R.id.animation_view)
LottieAnimationView animationView;
@Bind(R.id.restart)
ImageButton restart;
@Bind(R.id.play_button)
ImageButton playButton;
@Bind(R.id.loop)
ImageButton loop;
@Bind(R.id.fab)
FloatingActionButton fab;
@Bind(R.id.seek_bar)
AppCompatSeekBar seekBar;
private String mPage;
private ChooseAssetDialogFragment chooseAssetDialogFragment;
public static PageThreeFragment newInstance(String message) {
Bundle args = new Bundle();
args.putString(ARG_PAGE, message);
PageThreeFragment pageFragment = new PageThreeFragment();
pageFragment.setArguments(args);
return pageFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage = getArguments().getString(ARG_PAGE);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_three_page, null);
ButterKnife.bind(this, view);
isPlaying = true;
initListener();
return view;
}
private void initListener() {
fab.setOnClickListener(this);
restart.setOnClickListener(this);
playButton.setOnClickListener(this);
loop.setOnClickListener(this);
listener();
}
/**
* 动画监听
*/
private void listener() {
/**
* animationView控制seekBar
*/
animationView.addAnimatorUpdateListener(myAnimatorUpdateListener);
/**
* seekBar控制animationView
*/
seekBar.setOnSeekBarChangeListener(myOnSeekBarChangeListener);
/**
* 控制开关按钮状态
*/
animationView.addAnimatorListener(myAnimatorListener);
}
/**
* animationView控制seekBar
*/
private ValueAnimator.AnimatorUpdateListener myAnimatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
seekBar.setProgress((int) (valueAnimator.getAnimatedFraction() * 100));
}
};
/**
* seekBar控制animationView
*/
private SeekBar.OnSeekBarChangeListener myOnSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
animationView.setProgress(progress / 100f);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
/**
* 控制开关按钮状态
*/
private Animator.AnimatorListener myAnimatorListener = new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
if (isPlaying)
seekBar.setProgress(0);
playButton.setActivated(false);
}
@Override
public void onAnimationCancel(Animator animator) {
if (isPlaying)
seekBar.setProgress(0);
playButton.setActivated(false);
}
@Override
public void onAnimationRepeat(Animator animator) {
}
};
private boolean isPlaying = true;
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.fab://跳转到资源选择页面
animationView.cancelAnimation();
chooseAssetDialogFragment = ChooseAssetDialogFragment.newInstance();
chooseAssetDialogFragment.setTargetFragment(this, GO_DISLOG);
chooseAssetDialogFragment.show(getFragmentManager(), "assets");
break;
case R.id.loop://是否循环
loop.setActivated(!loop.isActivated());
// animationView.loop(loopButton.isEnabled());
animationView.loop(loop.isActivated());
break;
case R.id.restart://重新开始
isPlaying = true;
boolean restart = animationView.isAnimating();
animationView.cancelAnimation();
animationView.setProgress(0f);
if (restart) {
animationView.playAnimation();
}
break;
case R.id.play_button://播放与暂停
isPlaying = false;
if (animationView.isAnimating()) {
animationView.pauseAnimation();
postUpdatePlayButtonText();
} else {
if (animationView.getProgress() == 1f) {
animationView.setProgress(0f);
}
animationView.playAnimation();
postUpdatePlayButtonText();
}
break;
}
}
/**
* 改变播放状态
*/
private void postUpdatePlayButtonText() {
playButton.setActivated(animationView.isAnimating());
}
/**
* 回调
*
* @param requestCode
* @param resultCode
* @param data
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK) {
return;
}
switch (requestCode) {
case GO_DISLOG://资源选择回调
final String assetName = data.getStringExtra(EXTRA_ANIMATION_NAME);
LottieComposition.fromAssetFileName(getContext(), assetName,
new LottieComposition.OnCompositionLoadedListener() {
@Override
public void onCompositionLoaded(LottieComposition composition) {
setComposition(composition, assetName);
}
});
break;
}
}
/**
* 播放动画
*
* @param composition
* @param name
*/
private void setComposition(LottieComposition composition, String name) {
seekBar.setProgress(0);
animationView.setComposition(composition);
final Snackbar make = Snackbar.make(getView(), name, Snackbar.LENGTH_INDEFINITE);
make.show();
new Thread(new Runnable() {
@Override
public void run() {
SystemClock.sleep(2000);
if (make.isShown()) {
make.dismiss();
}
}
}).start();
}
@Override
public void onPause() {
super.onPause();
animationView.cancelAnimation();
/**
* animationView控制seekBar
*/
animationView.removeUpdateListener(myAnimatorUpdateListener);
/**
* 控制开关按钮状态
*/
animationView.removeAnimatorListener(myAnimatorListener);
}
@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
}
}
package cn.hnshangyu.lottie.fragment;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.io.IOException;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import cn.hnshangyu.lottie.R;
import cn.hnshangyu.lottie.adapter.MyAdapter;
import cn.hnshangyu.lottie.utils.AssetUtils;
/**
* 选择资源
*/
public class ChooseAssetDialogFragment extends DialogFragment {
@Bind(R.id.recycler_view)
RecyclerView recyclerView;
private List jsonAssets;
private MyAdapter mAdapter;
private Fragment targetFragment;
public static ChooseAssetDialogFragment newInstance() {
return new ChooseAssetDialogFragment();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_choose_asset, container, false);
ButterKnife.bind(this, view);
initData();
initView();
initListener();
return view;
}
private void initData() {
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
targetFragment = getTargetFragment();
try {
jsonAssets = AssetUtils.getJsonAssets(getContext(), "");
} catch (IOException e) {
e.printStackTrace();
Snackbar.make(getView(), "未找到资源", Snackbar.LENGTH_LONG).show();
}
}
private void initView() {
if (jsonAssets != null) {
mAdapter = new MyAdapter(getContext(), jsonAssets);
recyclerView.setAdapter(mAdapter);
}
}
private void initListener() {
if (mAdapter != null) {
mAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
@Override
public void OnClick(int position) {
targetFragment.onActivityResult(getTargetRequestCode(), Activity.RESULT_OK,
new Intent().putExtra(PageThreeFragment.EXTRA_ANIMATION_NAME, jsonAssets.get(position)));
dismiss();
}
});
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
}
}
package cn.hnshangyu.lottie.utils;
import android.content.Context;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* 获取Assets的资源
*/
public class AssetUtils {
public static List getJsonAssets(Context context, String path) throws IOException {
String[] assetList = context.getAssets().list(path);
List files = new ArrayList<>();
for (String asset : assetList) {
if (asset.toLowerCase().endsWith(".json")) {
files.add(asset);
}
}
return files;
}
}
- 效果四、 字体输入时效果:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:text="请输入字母:"
android:textColor="@color/colorAccent"
android:textSize="24sp" />
<cn.hnshangyu.lottie.view.LottieFontViewGroup
android:id="@+id/font_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
LinearLayout>
ScrollView>
package cn.hnshangyu.lottie.view;
import android.content.Context;
import android.support.annotation.Nullable;
import android.text.InputType;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.FrameLayout;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.model.LottieComposition;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cn.hnshangyu.lottie.R;
public class LottieFontViewGroup extends FrameLayout {
private final Map compositionMap = new HashMap<>();
private final List views = new ArrayList<>();
@Nullable private LottieAnimationView cursorView;
public LottieFontViewGroup(Context context) {
super(context);
init();
}
public LottieFontViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public LottieFontViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setFocusableInTouchMode(true);
LottieComposition.fromAssetFileName(getContext(), "Mobilo/BlinkingCursor.json",
new LottieComposition.OnCompositionLoadedListener() {
@Override
public void onCompositionLoaded(LottieComposition composition) {
cursorView = new LottieAnimationView(getContext());
cursorView.setLayoutParams(new LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
));
cursorView.setComposition(composition);
cursorView.loop(true);
cursorView.playAnimation();
addView(cursorView);
}
});
}
private void addSpace() {
int index = indexOfChild(cursorView);
addView(createSpaceView(), index);
}
@Override
public void addView(View child, int index) {
super.addView(child, index);
if (index == -1) {
views.add(child);
} else {
views.add(index, child);
}
}
private void removeLastView() {
if (views.size() > 1) {
int position = views.size() - 2;
removeView(views.get(position));
views.remove(position);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (views.isEmpty()) {
return;
}
int currentX = getPaddingTop();
int currentY = getPaddingLeft();
for (int i = 0; i < views.size(); i++) {
View view = views.get(i);
if (!fitsOnCurrentLine(currentX, view)) {
if (view.getTag() != null && view.getTag().equals("Space")) {
continue;
}
currentX = getPaddingLeft();
currentY += view.getMeasuredHeight();
}
currentX += view.getWidth();
}
setMeasuredDimension(getMeasuredWidth(),
currentY + views.get(views.size() - 1).getMeasuredHeight() * 2);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (views.isEmpty()) {
return;
}
int currentX = getPaddingTop();
int currentY = getPaddingLeft();
for (int i = 0; i < views.size(); i++) {
View view = views.get(i);
if (!fitsOnCurrentLine(currentX, view)) {
if (view.getTag() != null && view.getTag().equals("Space")) {
continue;
}
currentX = getPaddingLeft();
currentY += view.getMeasuredHeight();
}
view.layout(currentX, currentY, currentX + view.getMeasuredWidth(),
currentY + view.getMeasuredHeight());
currentX += view.getWidth();
}
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
BaseInputConnection fic = new BaseInputConnection(this, false);
outAttrs.actionLabel = null;
outAttrs.inputType = InputType.TYPE_NULL;
outAttrs.imeOptions = EditorInfo.IME_ACTION_NEXT;
return fic;
}
@Override
public boolean onCheckIsTextEditor() {
return true;
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SPACE) {
addSpace();
return true;
}
if (keyCode == KeyEvent.KEYCODE_DEL) {
removeLastView();
return true;
}
if (!isValidKey(event)) {
return super.onKeyUp(keyCode, event);
}
String letter = "" + Character.toUpperCase((char) event.getUnicodeChar());
// switch (letter) {
// case ",":
// letter = "Comma";
// break;
// case "'":
// letter = "Apostrophe";
// break;
// case ";":
// case ":":
// letter = "Colon";
// break;
// }
final String fileName = "Mobilo/" + letter + ".json";
if (compositionMap.containsKey(fileName)) {
addComposition(compositionMap.get(fileName));
} else {
LottieComposition.fromAssetFileName(getContext(), fileName,
new LottieComposition.OnCompositionLoadedListener() {
@Override
public void onCompositionLoaded(LottieComposition composition) {
compositionMap.put(fileName, composition);
addComposition(composition);
}
});
}
return true;
}
private boolean isValidKey(KeyEvent event) {
if (!event.hasNoModifiers()) {
return false;
}
if (event.getKeyCode() >= KeyEvent.KEYCODE_A && event.getKeyCode() <= KeyEvent.KEYCODE_Z) {
return true;
}
// switch (keyCode) {
// case KeyEvent.KEYCODE_COMMA:
// case KeyEvent.KEYCODE_APOSTROPHE:
// case KeyEvent.KEYCODE_SEMICOLON:
// return true;
// }
return false;
}
private void addComposition(LottieComposition composition) {
LottieAnimationView lottieAnimationView = new LottieAnimationView(getContext());
lottieAnimationView.setLayoutParams(new LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
));
lottieAnimationView.setComposition(composition);
lottieAnimationView.playAnimation();
if (cursorView == null) {
addView(lottieAnimationView);
} else {
int index = indexOfChild(cursorView);
addView(lottieAnimationView, index);
}
}
private boolean fitsOnCurrentLine(int currentX, View view) {
return currentX + view.getMeasuredWidth() < getWidth() - getPaddingRight();
}
private View createSpaceView() {
View spaceView = new View(getContext());
spaceView.setLayoutParams(new LayoutParams(
getResources().getDimensionPixelSize(R.dimen.font_space_width),
ViewGroup.LayoutParams.WRAP_CONTENT
));
spaceView.setTag("Space");
return spaceView;
}
}
package cn.hnshangyu.lottie.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.ScrollView;
import butterknife.Bind;
import butterknife.ButterKnife;
import cn.hnshangyu.lottie.R;
import cn.hnshangyu.lottie.view.LottieFontViewGroup;
public class PageFourFragment extends Fragment {
public static final String ARG_PAGE = "MESSAGE";
@Bind(R.id.font_view)
LottieFontViewGroup fontView;
@Bind(R.id.scroll_view)
ScrollView scrollView;
private String mPage;
public static PageFourFragment newInstance(String message) {
Bundle args = new Bundle();
args.putString(ARG_PAGE, message);
PageFourFragment pageFragment = new PageFourFragment();
pageFragment.setArguments(args);
return pageFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage = getArguments().getString(ARG_PAGE);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_four_page, null);
ButterKnife.bind(this, view);
fontView.getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
return view;
}
private ViewTreeObserver.OnGlobalLayoutListener layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
scrollView.fullScroll(View.FOCUS_DOWN);
}
};
@Override
public void onDestroyView() {
super.onDestroyView();
fontView.getViewTreeObserver().removeOnGlobalLayoutListener(layoutListener);
ButterKnife.unbind(this);
}
}
Demo下载地址:http://download.csdn.net/download/huangxiaoguo1/9760109