Android仿直播特效之刷礼物
一、概述
繼續咱們的直播之旅,過段時間再把推流拉流寫上博客,暫時還是UI特效,先上圖
二、創建我們的BaseActivity和BaseFrag
/*** @author 劉洋巴金* @date 2017-5-3* * 基類* */ public abstract class BaseActivity extends FragmentActivity implements OnClickListener{@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(getLayoutId());initBase();initView();initData();initListener();}/*** 設置子類getLayoutId* */public abstract int getLayoutId();/*** 基類初始化* */public void initBase() {}/*** 子類初始化View* */public void initView() {}/*** 子類初始化數據* */public void initData() {}/*** 子類初始化監聽* */public void initListener() {}@Overridepublic void onClick(View v) {} }
baseFrag
/*** @author 劉洋巴金* @date 2017-5-3* * Frag基類* */ public abstract class BaseFrag extends Fragment implements OnClickListener{public View view;public Context myContext;@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {view = inflater.inflate(getLayoutId(), null);// 初始化initBase();initView();initData();initListener();return view;}/*** 設置子類getLayoutId* */public abstract int getLayoutId();/*** 基類初始化* */public void initBase() {myContext = getActivity();}/*** 子類初始化View* */public void initView() {}/*** 子類初始化數據* */public void initData() {}/*** 子類初始化監聽* */public void initListener() {}@Overridepublic void onClick(View v) {} } 和baseActivity差不多 這個就是我們的基類,然后是我們的主類
/*** @author 劉洋巴金* @date 2017-5-3* * 主頁* */ public class MainActivity extends BaseActivity {@Overridepublic int getLayoutId() {return R.layout.activity_main;}@Overridepublic void initData() {super.initData();// 加載直播fragmentLiveFrag liveFrag = new LiveFrag();getSupportFragmentManager().beginTransaction().add(R.id.fl_root, liveFrag).commit();// 加載new InteractiveFrag().show(getSupportFragmentManager(), "InteractiveFrag");} }經過封裝簡單了很多吧?然后是加載fragment,LiveFrag就是我們的直播frag,現在目前為止就是一個圖片,以后增加拉流等相關功能,然后加載我們的用戶交互InteractiveFrag。
它是繼承DialogFragment,這個不明白的可以百度查詢,而這個也不是必須,可以自定義,
這里最主要的邏輯就是加了一個viewpager, 共加載了2個fragment,一個是我們交互用的,一個是透明的,這樣是為了滑動隱藏我們的交互的功能,如上圖最后的操作。EmptyFrag背景設置為透明,無任何邏輯
/*** 觀眾功能交互頁面, 滑動隱藏效果* * @author 劉洋巴金* @date 2017-5-3*/ public class InteractiveFrag extends DialogFragment{public View view;public Context myContext;private ViewPager vp_interactive;private LayerFrag layerFrag;@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {view = inflater.inflate(R.layout.frag_interactive, null);// 初始化initView();initData();initListener();return view;}/*** 初始化View* */public void initView() {vp_interactive = (ViewPager)view.findViewById(R.id.vp_interactive);}/*** 初始化數據* */public void initData() {// EmptyFrag:什么都沒有// LayerFrag:交互界面// 這樣就達到了滑動隱藏交互的需求vp_interactive.setAdapter(new FragmentPagerAdapter(getChildFragmentManager()) {@Overridepublic int getCount() {return 2;}@Overridepublic Fragment getItem(int position) {if (position == 0){return new EmptyFrag(); // 返回空界面的fragment}else if (position == 1){return layerFrag = new LayerFrag(); // 返回交互界面的frag}else{ // 設置默認return new EmptyFrag();}}});// 設置默認顯示交互界面vp_interactive.setCurrentItem(1);// 同時將界面改為resize已達到軟鍵盤彈出時Fragment不會跟隨移動getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);}/*** 初始化監聽* */public void initListener() {vp_interactive.setOnPageChangeListener(new OnPageChangeListener() {@Overridepublic void onPageSelected(int position) {if(position == 0){// layerFrag.hideKeyboard();}}@Overridepublic void onPageScrolled(int position, float arg1, int arg2) {}@Overridepublic void onPageScrollStateChanged(int position) {}});}@Overridepublic Dialog onCreateDialog(Bundle savedInstanceState) {// 設置DialogFragment的樣式,這里的代碼最好還是用我的,大家不要改動Dialog dialog = new Dialog(getActivity(), R.style.MainDialog){@Overridepublic void onBackPressed() {super.onBackPressed();getActivity().finish();}};return dialog;} } 三、實現我們的交互頁面
/*** 用戶交互頁* * @author 劉洋巴金* @date 2017-5-3*/ public class LayerFrag extends BaseFrag{private NumberAnim giftNumberAnim;private List<String> messageData = new LinkedList<>();private MessageAdapter messageAdapter;private ListView lv_message;private HorizontalListView hlv_audience;private LinearLayout ll_gift_group;private TranslateAnimation outAnim;private TranslateAnimation inAnim;private LinearLayout ll_inputparent;private Button tv_chat;private EditText et_chat;private LinearLayout ll_anchor;private RelativeLayout rl_num;@Overridepublic int getLayoutId() {// TODO Auto-generated method stubreturn R.layout.frag_layer;}@Overridepublic void initView() {// TODO Auto-generated method stubsuper.initView();lv_message = (ListView)view.findViewById(R.id.lv_message);hlv_audience = (HorizontalListView)view.findViewById(R.id.hlv_audience);ll_gift_group = (LinearLayout)view.findViewById(R.id.ll_gift_group);ll_inputparent = (LinearLayout)view.findViewById(R.id.ll_inputparent);tv_chat = (Button)view.findViewById(R.id.tv_chat);et_chat = (EditText)view.findViewById(R.id.et_chat);ll_anchor = (LinearLayout)view.findViewById(R.id.ll_anchor);rl_num = (RelativeLayout)view.findViewById(R.id.rl_num);}@Overridepublic void initData() {// TODO Auto-generated method stubsuper.initData();initAudience(); // 初始化觀眾initMessage(); // 初始化評論clearTiming(); // 開啟定時清理禮物列表initAnim(); // 初始化動畫} 進行初始化和變量聲明,首先初始化右上角的觀眾,其實就是個GridView,這里不再概述
/*** 初始化觀眾列表* */ private void initAudience() {hlv_audience.setAdapter(new AudienceAdapter(myContext)); }然后初始化評論,左下角底部的評論列表,listview不再概述
/*** 初始化評論列表* */ private void initMessage() {for(int x = 0; x < 20; x++){messageData.add("劉洋巴金: 主播好漂亮啊" + x);}messageAdapter = new MessageAdapter(getActivity(), messageData);lv_message.setAdapter(messageAdapter);lv_message.setSelection(messageData.size()); }初始化動畫
/*** 初始化動畫* */ private void initAnim() {giftNumberAnim = new NumberAnim(); // 初始化數字動畫inAnim = (TranslateAnimation) AnimationUtils.loadAnimation(getActivity(), R.anim.gift_in); // 禮物進入時動畫outAnim = (TranslateAnimation) AnimationUtils.loadAnimation(getActivity(), R.anim.gift_out); // 禮物退出時動畫 }
禮物的數字動畫,就是簡單的放大
clearTiming為禮物清理,3秒后自動清理,這個放在后面講,先開始刷禮物
@Override public void onClick(View v) {// TODO Auto-generated method stubsuper.onClick(v);switch (v.getId()) {case R.id.btn_gift01: // 禮物1,送香皂showGift("gift01");break;case R.id.btn_gift02: // 禮物2,送玫瑰showGift("gift02");break;case R.id.btn_gift03: // 禮物3,送愛心showGift("gift03");break;case R.id.btn_gift04: // 禮物4,送蛋糕showGift("gift04");break;4個按鈕的點擊事件
然后是刷禮物
/*** 刷禮物* */ private void showGift(String tag) {View newGiftView = ll_gift_group.findViewWithTag(tag);// 是否有該tag類型的禮物if(newGiftView == null){// 判斷禮物列表是否已經有3個了,如果有那么刪除掉一個沒更新過的, 然后再添加新進來的禮物,始終保持只有3個if(ll_gift_group.getChildCount() >= 3){// 獲取前2個元素的最后更新時間View giftView01 = ll_gift_group.getChildAt(0);ImageView iv_gift01 = (ImageView)giftView01.findViewById(R.id.iv_gift);long lastTime1 = (long) iv_gift01.getTag();View giftView02 = ll_gift_group.getChildAt(1);ImageView iv_gift02 = (ImageView)giftView02.findViewById(R.id.iv_gift);long lastTime2 = (long) iv_gift02.getTag();if (lastTime1 > lastTime2) { // 如果第二個View顯示的時間比較長removeGiftView(1);} else { // 如果第一個View顯示的時間長removeGiftView(0);}}// 獲取禮物newGiftView = getNewGiftView(tag);ll_gift_group.addView(newGiftView);// 播放動畫newGiftView.startAnimation(inAnim);final MagicTextView mtv_giftNum = (MagicTextView) newGiftView.findViewById(R.id.mtv_giftNum);inAnim.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {// TODO Auto-generated method stubgiftNumberAnim.showAnimator(mtv_giftNum);}});}else{...} }1.這段是核心代碼,首先評論去上方我們定義了一個LinearLayout,ll_gift_group,
2.然后根據點擊事件傳入tag,在 ll_gift_group查詢是否有該tag的子控件,也就是是否有該種類的禮物,如果沒有,判斷當前不同種類是否已經3個了,如果是,那么移除一個最先更新的禮物。
3.位置空出來了,生成我們的禮物
/*** 獲取禮物* */ private View getNewGiftView(String tag) {// 添加標識, 該view若在layout中存在,就不在生成(用于findViewWithTag判斷是否存在)View giftView = LayoutInflater.from(myContext).inflate(R.layout.item_gift, null);giftView.setTag(tag);// 添加標識, 記錄生成時間,回收時用于判斷是否是最新的,回收最老的ImageView iv_gift = (ImageView)giftView.findViewById(R.id.iv_gift);iv_gift.setTag(System.currentTimeMillis());// 添加標識,記錄禮物個數MagicTextView mtv_giftNum = (MagicTextView) giftView.findViewById(R.id.mtv_giftNum);mtv_giftNum.setTag(1);mtv_giftNum.setText("x1");switch (tag){case "gift01":iv_gift.setImageResource(GiftIcon[0]);break;case "gift02":iv_gift.setImageResource(GiftIcon[1]);break;case "gift03":iv_gift.setImageResource(GiftIcon[2]);break;case "gift04":iv_gift.setImageResource(GiftIcon[3]);break;}LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);lp.topMargin = 10;giftView.setLayoutParams(lp);return giftView; }1.生成我們的禮物控件,然后綁定tag進行標識,就是點擊事件傳遞過來的tag,
2.找其子控件,再綁定更新時間,因為要回收更新最早的控件,保留最后更新的
3.找其子控件,添加標識,記錄該種禮物的個數
4.設置禮物圖片
5.設置大小返回
好繼續回到我們的showGift方法
4.生成禮物后,添加到 ll_gift_group中,并執行進入動畫,MagicTextView為我們自定義的禮物數量的字體樣式,這個沒有規定可隨意自定義
5.禮物進入動畫執行完畢后,再執行數字動畫,就是放大
好了,然后我們又刷了一個禮物。
根據
View newGiftView = ll_gift_group.findViewWithTag(tag);判讀是否該類型的禮物還沒有被清理掉
如果是,那么我們走else
View newGiftView = ll_gift_group.findViewWithTag(tag);// 是否有該tag類型的禮物 if(newGiftView == null){... }else{// 如果列表中已經有了該類型的禮物,則不再新建,直接拿出// 更新標識,記錄最新修改的時間,用于回收判斷ImageView iv_gift = (ImageView)newGiftView.findViewById(R.id.iv_gift);iv_gift.setTag(System.currentTimeMillis());// 更新標識,更新記錄禮物個數MagicTextView mtv_giftNum = (MagicTextView) newGiftView.findViewById(R.id.mtv_giftNum);int giftCount = (int) mtv_giftNum.getTag() + 1; // 遞增mtv_giftNum.setText("x" + giftCount);mtv_giftNum.setTag(giftCount);giftNumberAnim.showAnimator(mtv_giftNum); }1.首先拿出禮物控件的子控件,更新它的更新時間
2.然后再拿出其子控件更新他的禮物數量的標識。
3.更改UI,執行數字動畫
這樣禮物就刷出去了,但是為了用戶體驗,禮物要3秒鐘之后消失
/*** 定時清理禮物列表信息*/ private void clearTiming() {Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {int childCount = ll_gift_group.getChildCount();long nowTime = System.currentTimeMillis();for (int i = 0; i < childCount; i++) {View childView = ll_gift_group.getChildAt(i);ImageView iv_gift = (ImageView)childView.findViewById(R.id.iv_gift);long lastUpdateTime = (long) iv_gift.getTag();// 更新超過3秒就刷新if(nowTime - lastUpdateTime >= 3000){removeGiftView(i);}}}}, 0, 3000); }這個就比較簡單了,拿出?ll_gift_group中全部的控件,遍歷他們,取出他們最后更新的時間,然后對比當前時間,如果誰的時間超過3秒了,那么執行移除
/*** 移除禮物列表里的giftView* */ private void removeGiftView(final int index) {// 移除列表,外加退出動畫final View removeGiftView = ll_gift_group.getChildAt(index);outAnim.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {// TODO Auto-generated method stubll_gift_group.removeViewAt(index);}});// 開啟動畫,因為定時原因,所以可能是在子線程getActivity().runOnUiThread(new Runnable() {@Overridepublic void run() {removeGiftView.startAnimation(outAnim);}}); }移除禮物,然后執行退出動畫。
好了刷禮物就到這吧,不明白的話,底下評論
四、demo
Android仿直播特效之刷禮物
總結
以上是生活随笔為你收集整理的Android仿直播特效之刷礼物的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux 日志打印到文件的2种方式
- 下一篇: 质感设计 android,扣丁学堂And