lottie开源库的诞生为我们动画的设置可谓提供了很大的便利,我们可以直接使用设计师用AE产生的json格式动画坐标,进行操作,简单快捷……

  • 那么首先我们来看看效果:

  • 引入Lottie
dependencies {  compile 'com.airbnb.android:lottie:1.0.3'
}
  • 在MainActivity中创建4中效果页面
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<Fragment> fragmentList = new ArrayList<>();private ViewPagerAdapter viewPagerAdapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ButterKnife.bind(this);// 用toolBar替换ActionBarsetToolBarReplaceActionBar();//创建fragmentcreateFragment();// 给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() {@Overridepublic void onClick(View view) {snackbar = Snackbar.make(view, "确定要退出程序吗?", Snackbar.LENGTH_INDEFINITE);snackbar.setAction("退出", new View.OnClickListener() {@Overridepublic void onClick(View view) {MainActivity.this.finish();}}).show();new Thread(new Runnable() {@Overridepublic 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);}}
  • 资产目录如下所示:(主要放置。json文件)

效果一、lottie简单动画实现

 1. 布局如下:
<?xml version="1.0" encoding="utf-8"?>
<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" /><!--添加播放源,注意资源在assets中--><!--app:lottie_fileName="Logo/LogoSmall.json"--><!--是否循环播放--><!-- app:lottie_loop="true"--><!--自动播放--><!--app:lottie_autoPlay="true"-->
</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;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mPage = getArguments().getString(ARG_PAGE);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, BundlesavedInstanceState) {View view = inflater.inflate(R.layout.fragment_one_page, null);ButterKnife.bind(this, view);return view;}/*** 播放动画*/@Overridepublic 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();}/*** 停止动画*/@Overridepublic void onPause() {super.onPause();animationView.cancelAnimation();}@Overridepublic void onDestroyView() {super.onDestroyView();ButterKnife.unbind(this);}
}

效果二、动画播放的监听

1.布局文件
<?xml version="1.0" encoding="utf-8"?>
<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;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mPage = getArguments().getString(ARG_PAGE);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, BundlesavedInstanceState) {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() {@Overridepublic void onClick(View view) {animationView.removeAnimatorListener(myAnimatorListener);animationPosition = 0;startAnimation();}});stop.setOnClickListener(new View.OnClickListener() {@Overridepublic 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() {@Overridepublic void onAnimationStart(Animator animator) {Log.e("huangxiaoguo", "onAnimationStart");//开始animationPosition = animationPosition + 1;}@Overridepublic 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();}}@Overridepublic void onAnimationCancel(Animator animator) {Log.e("huangxiaoguo", "onAnimationCancel");//取消}@Overridepublic void onAnimationRepeat(Animator animator) {Log.e("huangxiaoguo", "onAnimationRepeat");//重复}};/*** 停止动画*/@Overridepublic void onPause() {super.onPause();animationPosition = JsonList.length + 1;animationView.cancelAnimation();}@Overridepublic void onDestroyView() {super.onDestroyView();ButterKnife.unbind(this);}
}

效果三、动画播放暂停,重新播放、循环播放等一系列设置

  • 布局文件
<?xml version="1.0" encoding="utf-8"?>
<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;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mPage = getArguments().getString(ARG_PAGE);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, BundlesavedInstanceState) {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() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {seekBar.setProgress((int) (valueAnimator.getAnimatedFraction() * 100));}};/*** seekBar控制animationView*/private SeekBar.OnSeekBarChangeListener myOnSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {animationView.setProgress(progress / 100f);}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}};/*** 控制开关按钮状态*/private Animator.AnimatorListener myAnimatorListener = new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animator) {}@Overridepublic void onAnimationEnd(Animator animator) {if (isPlaying)seekBar.setProgress(0);playButton.setActivated(false);}@Overridepublic void onAnimationCancel(Animator animator) {if (isPlaying)seekBar.setProgress(0);playButton.setActivated(false);}@Overridepublic void onAnimationRepeat(Animator animator) {}};private boolean isPlaying = true;@Overridepublic 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*/@Overridepublic 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() {@Overridepublic 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() {@Overridepublic void run() {SystemClock.sleep(2000);if (make.isShown()) {make.dismiss();}}}).start();}@Overridepublic void onPause() {super.onPause();animationView.cancelAnimation();/*** animationView控制seekBar*/animationView.removeUpdateListener(myAnimatorUpdateListener);/*** 控制开关按钮状态*/animationView.removeAnimatorListener(myAnimatorListener);}@Overridepublic void onDestroyView() {super.onDestroyView();ButterKnife.unbind(this);}
}
  • ChooseAssetDialogFragment
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<String> jsonAssets;private MyAdapter mAdapter;private Fragment targetFragment;public static ChooseAssetDialogFragment newInstance() {return new ChooseAssetDialogFragment();}@Overridepublic 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() {@Overridepublic void OnClick(int position) {targetFragment.onActivityResult(getTargetRequestCode(), Activity.RESULT_OK,new Intent().putExtra(PageThreeFragment.EXTRA_ANIMATION_NAME, jsonAssets.get(position)));dismiss();}});}}@Overridepublic void onDestroyView() {super.onDestroyView();ButterKnife.unbind(this);}
}
  • 获取Assets的资源
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<String> getJsonAssets(Context context, String path) throws IOException {String[] assetList = context.getAssets().list(path);List<String> files = new ArrayList<>();for (String asset : assetList) {if (asset.toLowerCase().endsWith(".json")) {files.add(asset);}}return files;}
}

- 效果四、 字体输入时效果:

  • 布局
<?xml version="1.0" encoding="utf-8"?>
<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>
  • 自定义LottieFontViewGroup
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<String, LottieComposition> compositionMap = new HashMap<>();private final List<View> 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() {@Overridepublic 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);}@Overridepublic 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);}}@Overrideprotected 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);}@Overrideprotected 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();}}@Overridepublic 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;}@Overridepublic boolean onCheckIsTextEditor() {return true;}@Overridepublic 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() {@Overridepublic 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;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mPage = getArguments().getString(ARG_PAGE);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, BundlesavedInstanceState) {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() {@Overridepublic void onGlobalLayout() {scrollView.fullScroll(View.FOCUS_DOWN);}};@Overridepublic void onDestroyView() {super.onDestroyView();fontView.getViewTreeObserver().removeOnGlobalLayoutListener(layoutListener);ButterKnife.unbind(this);}
}

Demo下载地址:http://download.csdn.net/download/huangxiaoguo1/9760109

lottie动画效果使用简例相关推荐

  1. [Mapbox GL]点的动画效果

    更新每帧的GeoJSON资源实现点的动画效果 <!DOCTYPE html> <html> <head><meta charset='utf-8' /> ...

  2. Lottie 站在巨人的肩膀上实现 Android 酷炫动画效果

    说到动画效果,一般都会感到很高端,感觉很酷炫:而小菜技术有限,稍复杂的动画效果也需要很多时间处理,但是遇到时间紧任务重的情况该怎么办呢?那就尝试一下 Lottie 吧,酷炫的动画集成却相当简单,还支持 ...

  3. android 添加json动画,Lottie 站在巨人的肩膀上实现 Android 酷炫动画效果

    说到动画效果,一般都会感到很高端,感觉很酷炫:而小菜技术有限,稍复杂的动画效果也需要很多时间处理,但是遇到时间紧任务重的情况该怎么办呢?那就尝试一下 Lottie 是个啥? Lottie 咋集成?bu ...

  4. lottie实现动画效果

    1.lottie的安装 npm install lottie-web --save 2.创建一个子组件,用来封装lottie动画 <template><!-- 为容器绑定样式 --& ...

  5. 逐帧动画效果——简单篇

    当我们制作一些通过属性变化无法实现的动画效果时,就需要使用逐帧动画. 现在lllustrator 矢量图绘图软件中绘制好跑步动作的每一个环节(这里我借鉴书上的图): 这里图像的每一帧内容都是 300x ...

  6. 前端三件套系例之JQuery——JQuery动画效果、JQuery插件、

    文章目录 1 JQuery动画效果 1. 基本效果 2. 滑动效果 3 淡入淡出效果 4 自定义动画 5 动画控制 6 设置 7 事件 7-1 常用事件 7-2 事件绑定 7-3 移除事件 7-4 阻 ...

  7. python能制作ppt动画效果吗_那些超酷的视频效果,真的是用PPT动画做的吗?

    作为一名5年经验的PPT设计师,我负责任的讲:真的是PPT做的! 用PPT轻松做出网页效果: 还有这种交互: 还有苹果的网页动画: 等等,太多了,都是可以轻松用PPT实现的,可能只是一个简单的动画添加 ...

  8. mysql 工具 uwp_UWP 创建动画的极简方式 — LottieUWP

    提到 UWP 中创建动画,第一个想到的大多都是 StoryBoard.因为 UWP 和 WPF 的界面都是基于 XAML 语言的,所以实现 StoryBoard 会非常方便. 来看一个简单的 Stor ...

  9. Unity 之 UGUI Toggle组件介绍和简例

    Unity 之 UGUI Toggle组件介绍和简例 复合组件Toggle的组成: Toggle:自身挂载Toggle组件,并且对有对子物体的引用. Background:就是个Image组件,用来当 ...

  10. iOS Lottie动画框架使用 AE导出JSON文件

    介绍 Airbnb团队 发布的 Lottie 是一个面向 iOS.Android 和 React Native 的跨平台的开源动画库. Lottie可以直接利用 AE上的bodymovin插件导出的 ...

最新文章

  1. 字节跳动教育裁员:赔付方式N+2
  2. Intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他
  3. DAO、Service、Controller及View层级结构梳理
  4. 单件模式(Singleton Pattern)(转自TerryLee)
  5. CSS学习笔记(更新中...)
  6. SQLServer无法使用特殊主体'sa'的解决
  7. 余数计算方法及其使用方法
  8. 【解决】Git:hint:Pulling without specifying how to reconclie divergent branches is...
  9. 《龙腾世纪2》图文流程攻略
  10. 基于JAVA城市湖泊信息管理系统计算机毕业设计源码+系统+lw文档+部署
  11. 遇见狂神书说:JavaWeb保姆级教程
  12. 从git上克隆的vue项目在本地运行步骤
  13. swiper插件在ie浏览器无反应,解决办法
  14. 多国语言在线客服系统源码+软件下载二合一集成
  15. 如何选好网络项目,五条建议避免你踩坑
  16. 思维导图TheBrain基础实操教程——查找、添加附件和链接
  17. 《用PS给照片换底》
  18. 智能汽车数据安全与法律法规盘点
  19. java实现通过url实现浏览器下载pdf文件
  20. OpenCV——几种图像滤波总结(python实现和c++实现)

热门文章

  1. kuangbin 简单搜索 A 棋盘问题
  2. 【蓝牙串口无线烧写程序】适用于STM32F103和STM32F107的Bootloader
  3. si4463如何读取RSSI
  4. 微信java sdk 多公众号_Java版微信公众号支付开发全过程
  5. 未来10年,最值得投资的40个城市
  6. SECS/GEM通信
  7. 用户自治的数字身份在我国的标准
  8. 接入阿里云云呼叫中心
  9. java设计模式-终结者者模式
  10. 在线全网音乐搜索下载源码