안 드 로 이 드 생방송 앱 선물 증정 기능

생방송 인터페이스
로 컬 비디오 파일 재생:

/**
 *     ,        
 */
public class LiveFrag extends Fragment {

 private ImageView img_thumb;
 private VideoView video_view;

 @Nullable
 @Override
 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
 View view = inflater.inflate(R.layout.frag_live, null);
 img_thumb = view.findViewById(R.id.img_thumb);
 img_thumb.setVisibility(View.GONE);
 video_view = view.findViewById(R.id.video_view);
 video_view.setVisibility(View.VISIBLE);
 video_view.setVideoURI(Uri.parse("android.resource://" + getActivity().getPackageName() + "/" + R.raw.video_1));
 video_view.start();
 video_view.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
 @Override
 public void onCompletion(MediaPlayer mp) {
 video_view.setVideoURI(Uri.parse("android.resource://" + getActivity().getPackageName() + "/" + R.raw.video_1));
 //  //mVideoView.setVideoPath(Uri.parse(_filePath));
 video_view.start();
 }
 });
 return view;
 }
}
레이아웃 파일 fraglive.xml 는 다음 과 같 습 니 다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">
 <VideoView
 android:id="@+id/video_view"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:clickable="false"
 android:focusable="false"
 android:visibility="gone" />
 <ImageView
 android:id="@+id/img_thumb"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:clickable="false"
 android:focusable="false"
 android:scaleType="centerCrop"
 android:src="@mipmap/img_video_1"
 android:visibility="visible" />
</LinearLayout>
미끄럼 숨 김 효과
실현 해 야 할 효 과 는 다음 과 같다.

DialogFragment 를 사용자 정의 합 니 다.ViewPager 를 사용 합 니 다.첫 번 째 는 빈 Fragment 이 고 두 번 째 는 우리 가 필요 로 하 는 Fragment 입 니 다.좌우 로 미 끄 러 지 며 디 스 플레이 와 숨 김 효 과 를 전환 합 니 다.
관중 기능 인 터 랙 션 페이지 InteractiveFrag 는 다음 과 같다.

/**
 *         ,       
 */
public class InteractiveFrag extends DialogFragment {

 public View view;
 public Context myContext;
 private ViewPager vp_interactive;
 private LayerFrag layerFrag;

 @Override
 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
 view = inflater.inflate(R.layout.frag_interactive, null);
 //    
 initView();
 initData();
 return view;
 }

 /**
 *    View
 */
 public void initView() {
 vp_interactive = view.findViewById(R.id.vp_interactive);
 }

 /**
 *      
 */
 public void initData() {
 // EmptyFrag:     
 // LayerFrag:    
 //                
 vp_interactive.setAdapter(new FragmentPagerAdapter(getChildFragmentManager()) {
 @Override
 public int getCount() {
 return 2;
 }

 @Override
 public 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);
 }

 @Override
 public Dialog onCreateDialog(Bundle savedInstanceState) {

 //   DialogFragment   ,            ,      
 Dialog dialog = new Dialog(getActivity(), R.style.MainDialog) {

 @Override
 public void onBackPressed() {
 super.onBackPressed();
 getActivity().finish();
 }
 };
 return dialog;
 }
}
frag_interactive.xml 파일 은 다음 과 같 습 니 다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical" >

 <androidx.viewpager.widget.ViewPager
 android:id="@+id/vp_interactive"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />
</LinearLayout>
사용자 대화 페이지 LayerFrag:

public class LayerFrag extends Fragment {
 @Nullable
 @Override
 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
 return inflater.inflate(R.layout.frag_layer, null);
 }
}

frag_layer:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">
 <LinearLayout
 android:id="@+id/ll_anchor"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:gravity="center_vertical"
 android:orientation="horizontal"
 android:paddingLeft="10dp"
 android:paddingTop="10dp">
 <RelativeLayout
 android:layout_width="wrap_content"
 android:layout_height="wrap_content">
 <LinearLayout
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_centerVertical="true"
 android:background="@drawable/bg_radius_top_black"
 android:gravity="center_vertical"
 android:orientation="vertical"
 android:paddingLeft="55dp"
 android:paddingTop="2dp"
 android:paddingRight="10dp"
 android:paddingBottom="2dp">
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="    "
 android:textColor="@android:color/white"
 android:textSize="12sp" />
 <LinearLayout
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:gravity="center_vertical"
 android:orientation="horizontal">
 <ImageView
 android:layout_width="35dp"
 android:layout_height="20dp"
 android:src="@drawable/hani_icon_tag_exp" />
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginLeft="5dp"
 android:text="17 "
 android:textColor="@android:color/white"
 android:textSize="10sp" />
 </LinearLayout>
 </LinearLayout>
 <com.hongx.zhibo.utils.CircleImageView
 android:id="@+id/lv_anchorIcon"
 android:layout_width="50dp"
 android:layout_height="50dp"
 android:src="@drawable/zf"
 app:border_color="@color/colorWhite"
 app:border_width="1dp" />
 </RelativeLayout>
 <com.hongx.zhibo.utils.HorizontalListView
 android:id="@+id/hlv_audience"
 android:layout_width="match_parent"
 android:layout_height="45dp"
 android:layout_marginLeft="10dp" />
 </LinearLayout>
 <RelativeLayout
 android:id="@+id/rl_num"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_below="@+id/ll_anchor"
 android:layout_marginTop="5dp"
 android:paddingLeft="10dp"
 android:paddingRight="10dp">
 <LinearLayout
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:background="@drawable/bg_radius_bottom_pink"
 android:gravity="center_vertical"
 android:paddingLeft="10dp"
 android:paddingTop="2dp"
 android:paddingRight="10dp"
 android:paddingBottom="2dp">
 <ImageView
 android:layout_width="20dp"
 android:layout_height="10dp"
 android:src="@drawable/molive_icon_charm_lv_20" />
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginLeft="5dp"
 android:text="     5 "
 android:textColor="#fff"
 android:textSize="10sp" />
 </LinearLayout>
 <TextView
 android:id="@+id/tv_momocode"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignParentRight="true"
 android:layout_centerVertical="true"
 android:background="@drawable/bg_radius_top_black"
 android:paddingLeft="10dp"
 android:paddingTop="2dp"
 android:paddingRight="10dp"
 android:paddingBottom="2dp"
 android:text="MoMo: 12345678"
 android:textColor="@android:color/white"
 android:textSize="10sp" />
 </RelativeLayout>
 <LinearLayout
 android:id="@+id/ll_gift_group"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_above="@+id/lv_message"
 android:layout_marginTop="10dp"
 android:layout_marginBottom="10dp"
 android:animateLayoutChanges="true"
 android:gravity="top"
 android:orientation="vertical" />
 <ListView
 android:id="@+id/lv_message"
 android:layout_width="230dp"
 android:layout_height="150dp"
 android:layout_above="@+id/fl_bottom"
 android:layout_marginLeft="10dp"
 android:cacheColorHint="#00000000"
 android:divider="@null"
 android:dividerHeight="5dp"
 android:listSelector="#00000000"
 android:scrollbarStyle="outsideOverlay"
 android:scrollbars="none"
 android:transcriptMode="normal" />
 <FrameLayout
 android:id="@+id/fl_bottom"
 android:layout_width="match_parent"
 android:layout_height="70dp"
 android:layout_alignParentStart="true"
 android:layout_alignParentBottom="true">
 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@android:color/transparent"
 android:gravity="center_vertical"
 android:orientation="horizontal"
 android:paddingLeft="10dp"
 android:paddingRight="10dp">
 <Button
 android:id="@+id/tv_chat"
 android:layout_width="40dp"
 android:layout_height="70dp"
 android:gravity="center"
 android:text="  "
 android:textColor="#333"
 android:textSize="10sp" />
 <View
 android:layout_width="0dp"
 android:layout_height="1dp"
 android:layout_weight="1" />
 <Button
 android:id="@+id/btn_gift01"
 android:layout_width="40dp"
 android:layout_height="70dp"
 android:layout_marginRight="5dp"
 android:gravity="center"
 android:text="   "
 android:textColor="#333"
 android:textSize="12sp" />
 <Button
 android:id="@+id/btn_gift02"
 android:layout_width="40dp"
 android:layout_height="70dp"
 android:layout_marginRight="5dp"
 android:gravity="center"
 android:text="   "
 android:textColor="#333"
 android:textSize="12sp" />
 <Button
 android:id="@+id/btn_gift03"
 android:layout_width="40dp"
 android:layout_height="70dp"
 android:layout_marginRight="5dp"
 android:gravity="center"
 android:text="   "
 android:textColor="#333"
 android:textSize="12sp" />
 <Button
 android:id="@+id/btn_gift04"
 android:layout_width="40dp"
 android:layout_height="70dp"
 android:layout_marginRight="5dp"
 android:gravity="center"
 android:text="   "
 android:textColor="#333"
 android:textSize="12sp" />
 </LinearLayout>
 <LinearLayout
 android:id="@+id/ll_inputparent"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_marginTop="5dp"
 android:background="@android:color/white"
 android:paddingLeft="10dp"
 android:paddingRight="10dp"
 android:visibility="gone">
 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:gravity="center_vertical"
 android:orientation="horizontal">
 <EditText
 android:id="@+id/et_chat"
 android:layout_width="0dp"
 android:layout_height="wrap_content"
 android:layout_weight="1"
 android:background="@android:color/white"
 android:hint="         !"
 android:maxLength="30"
 android:paddingTop="10dp"
 android:paddingBottom="10dp"
 android:textColor="#888889"
 android:textColorHint="#c8c8c8"
 android:textSize="12sp" />
 <TextView
 android:id="@+id/tv_send"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginLeft="10dp"
 android:background="@android:color/holo_blue_bright"
 android:paddingLeft="10dp"
 android:paddingTop="5dp"
 android:paddingRight="10dp"
 android:paddingBottom="5dp"
 android:text="  "
 android:textColor="@android:color/white"
 android:textSize="12sp" />
 </LinearLayout>
 </LinearLayout>
 </FrameLayout>
</RelativeLayout>

EmptyFrag:

/**
 *   fragment
 */
public class EmptyFrag extends Fragment {
 @Nullable
 @Override
 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
 return inflater.inflate(R.layout.frag_empty, null);
 }
}

frag_empty.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@android:color/transparent"
 android:orientation="vertical">
</LinearLayout>

MainActivity 에서 FrameLayout 레이아웃 을 사용 하여 시청자 기능 의 상호작용 페이지 인 InteractiveFrag 를 생방송 페이지 인 LiveFrag 에 덮어 씁 니 다.
MainActivity:

public class MainActivity extends AppCompatActivity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 //     fragment
 LiveFrag liveFrag = new LiveFrag();
 getSupportFragmentManager().beginTransaction().add(R.id.fl_root, liveFrag).commit();
 //   
 new InteractiveFrag().show(getSupportFragmentManager(), "InteractiveFrag");
 }
}

activity_main.xml :

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 <FrameLayout
 android:id="@+id/fl_root"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />
</RelativeLayout>
사용자 대화 페이지 구현
MagicTextView 애니메이션 효과
MagicTextView 코드 는 글 의 마지막 에 보 여 줍 니 다.
우 리 는 먼저 다음 과 같은 애니메이션 효 과 를 실현 합 니 다.

<com.hongx.zhibo.utils.MagicTextView
 android:id="@+id/mtv_giftNum"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_centerVertical="true"
 android:layout_marginLeft="5dp"
 android:layout_toRightOf="@+id/rlparent"
 android:includeFontPadding="false"
 android:text="x1"
 android:textColor="@android:color/holo_red_dark"
 android:textSize="30sp"
 android:textStyle="bold"
 app:strokeColor="@android:color/white"
 app:strokeJoinStyle="miter"
 app:strokeWidth="2" />

애니메이션:

 public class NumberAnim {
 private Animator lastAnimator;
 public void showAnimator(View v) {
 if (lastAnimator != null) {
 lastAnimator.removeAllListeners();
 lastAnimator.cancel();
 lastAnimator.end();
 }
 ObjectAnimator animScaleX = ObjectAnimator.ofFloat(v, "scaleX", 1.3f, 1.0f);
 ObjectAnimator animScaleY = ObjectAnimator.ofFloat(v, "scaleY", 1.3f, 1.0f);
 AnimatorSet animSet = new AnimatorSet();
 animSet.playTogether(animScaleX, animScaleY);
 animSet.setDuration(200);
 lastAnimator = animSet;
 animSet.start();
 }
 }

 mtv_giftNum.setText("x" + count);
 giftNumberAnim = new NumberAnim(); //         
 mtv_giftNum.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 count++;
 mtv_giftNum.setText("x" + count);
 giftNumberAnim.showAnimator(mtv_giftNum);
 }
 });
선물 입장 시 애니메이션

애니메이션 입장 시 decelerate 로 설정interpolator 감속 플러그 인:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
 android:duration="500"
 android:fromXDelta="-100%p"
 android:interpolator="@android:anim/decelerate_interpolator"
 android:toYDelta="0%p">
</translate>

 /**
 *       
 */
 private void showGift(String tag) {
 View newGiftView = ll_gift_group.findViewWithTag(tag);
 //     tag     
 if (newGiftView == null) {
 //     
 newGiftView = getNewGiftView(tag);
 ll_gift_group.addView(newGiftView);

 //     
 newGiftView.startAnimation(inAnim);
 final MagicTextView mtv_giftNum = newGiftView.findViewById(R.id.mtv_giftNum);
 inAnim.setAnimationListener(new Animation.AnimationListener() {

 @Override
 public void onAnimationStart(Animation animation) {
 }

 @Override
 public void onAnimationRepeat(Animation animation) {
 }

 @Override
 public void onAnimationEnd(Animation animation) {
 giftNumberAnim.showAnimator(mtv_giftNum);
 }
 });
 } else {
 //                ,     ,    
 //     ,         ,      
 ImageView iv_gift = newGiftView.findViewById(R.id.iv_gift);
 iv_gift.setTag(System.currentTimeMillis());

 //     ,        
 MagicTextView mtv_giftNum = 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);
 }
 }

 /**
 *     
 */
 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 = giftView.findViewById(R.id.iv_gift);
 iv_gift.setTag(System.currentTimeMillis());

 //     ,      
 MagicTextView mtv_giftNum = 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;
 }

 @Override
 public void onClick(View 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;
 }
 }
선물 이동 애니메이션
실현 효 과 는 다음 과 같다.

선물 이동 시 accelerate 사용interpolator 가속 차 치 기

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
 android:duration="500"
 android:fromYDelta="0%p"
 android:interpolator="@android:anim/accelerate_interpolator"
 android:toYDelta="-100%p">
</translate>

 /**
 *         giftView
 */
 private void removeGiftView(final int index) {
 //     ,      
 final View removeGiftView = ll_gift_group.getChildAt(index);
 outAnim.setAnimationListener(new Animation.AnimationListener() {

 @Override
 public void onAnimationStart(Animation animation) {
 }

 @Override
 public void onAnimationRepeat(Animation animation) {
 }

 @Override
 public void onAnimationEnd(Animation animation) {
 ll_gift_group.removeViewAt(index);
 }
 });

 //     ,      ,         
 getActivity().runOnUiThread(new Runnable() {
 @Override
 public void run() {
 removeGiftView.startAnimation(outAnim);
 }
 });
 }
표시 되 는 선물 이 3 가지 이상 이면 최초의 선물 을 제거 합 니 다.

//     tag     
 if (newGiftView == null) {
 //            3  ,               ,            ,      3 
 if (ll_gift_group.getChildCount() >= 3) {
 //    2          
 View giftView01 = ll_gift_group.getChildAt(0);
 ImageView iv_gift01 = giftView01.findViewById(R.id.iv_gift);
 long lastTime1 = (long) iv_gift01.getTag();

 View giftView02 = ll_gift_group.getChildAt(1);
 ImageView iv_gift02 = giftView02.findViewById(R.id.iv_gift);
 long lastTime2 = (long) iv_gift02.getTag();

 if (lastTime1 > lastTime2) { //      View        
 removeGiftView(1);
 } else { //      View      
 removeGiftView(0);
 }
 }
...

오픈 정시 선물 리스트 정리
선물 은 일정 시간 이 지나 면 선물 목록 에서 자동 으로 삭 제 됩 니 다:

 /**
 *           
 */
 private void clearTiming() {
 Timer timer = new Timer();
 timer.schedule(new TimerTask() {

 @Override
 public 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);
 }

채 팅 실현

case R.id.tv_chat://   
 tv_chat.setVisibility(View.GONE);
 ll_inputparent.setVisibility(View.VISIBLE);
 ll_inputparent.requestFocus(); //     
 showKeyboard();
 break;
 case R.id.tv_send://     
 String chatMsg = et_chat.getText().toString();
 if (!TextUtils.isEmpty(chatMsg)) {
 messageData.add("  : " + chatMsg);
 et_chat.setText("");
 messageAdapter.NotifyAdapter(messageData);
 lv_message.setSelection(messageData.size());
 }
 hideKeyboard();
 break;

 /**
 *      
 */
 private void showKeyboard() {
 InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
 imm.showSoftInput(et_chat, InputMethodManager.SHOW_FORCED);
 }

 /**
 *      
 */
 public void hideKeyboard() {
 InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
 imm.hideSoftInputFromWindow(et_chat.getWindowToken(), 0);
 }

 view.setOnClickListener(new View.OnClickListener() {

 @Override
 public void onClick(View v) {
 if (ll_inputparent.getVisibility() == View.VISIBLE) {
 tv_chat.setVisibility(View.VISIBLE);
 ll_inputparent.setVisibility(View.GONE);
 hideKeyboard();
 }
 }
 });

 //      
 SoftKeyBoardListener.setListener(getActivity(), new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() {
 @Override
 public void keyBoardShow(int height) {/*     :    title  ,   listview            */

 //             
 AnimatorSet animatorSetHide = new AnimatorSet();
 ObjectAnimator leftOutAnim = ObjectAnimator.ofFloat(rl_num, "translationX", 0, -rl_num.getWidth());
 ObjectAnimator topOutAnim = ObjectAnimator.ofFloat(ll_anchor, "translationY", 0, -ll_anchor.getHeight());
 animatorSetHide.playTogether(leftOutAnim, topOutAnim);
 animatorSetHide.setDuration(300);
 animatorSetHide.start();
 //   listview   
 dynamicChangeListviewH(90);
 dynamicChangeGiftParentH(true);
 }

 @Override
 public void keyBoardHide(int height) {/*     :              ,    title  ,   listview            */
 tv_chat.setVisibility(View.VISIBLE);
 ll_inputparent.setVisibility(View.GONE);
 //               
 AnimatorSet animatorSetShow = new AnimatorSet();
 ObjectAnimator leftInAnim = ObjectAnimator.ofFloat(rl_num, "translationX", -rl_num.getWidth(), 0);
 ObjectAnimator topInAnim = ObjectAnimator.ofFloat(ll_anchor, "translationY", -ll_anchor.getHeight(), 0);
 animatorSetShow.playTogether(leftInAnim, topInAnim);
 animatorSetShow.setDuration(300);
 animatorSetShow.start();

 //   listview   
 dynamicChangeListviewH(150);
 dynamicChangeGiftParentH(false);
 }
 });

 /**
 *      listview   
 */
 private void dynamicChangeListviewH(int heightPX) {
 ViewGroup.LayoutParams layoutParams = lv_message.getLayoutParams();
 layoutParams.height = DisplayUtil.dip2px(getActivity(), heightPX);
 lv_message.setLayoutParams(layoutParams);
 }

 /**
 *             
 */
 private void dynamicChangeGiftParentH(boolean showhide) {
 if (showhide) {//         
 if (ll_gift_group.getChildCount() != 0) {

 //          ,           ,           
 ViewGroup.LayoutParams layoutParams = ll_gift_group.getLayoutParams();
 layoutParams.height = ll_gift_group.getChildAt(0).getHeight();
 ll_gift_group.setLayoutParams(layoutParams);
 }
 } else {
 //         
 //                    
 ViewGroup.LayoutParams layoutParams = ll_gift_group.getLayoutParams();
 layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
 ll_gift_group.setLayoutParams(layoutParams);
 }
 }

MagicTextView 코드

/**
 *     view          ,     ,   ,   
 */
public class MagicTextView extends TextView {
 private ArrayList<Shadow> outerShadows;
 private ArrayList<Shadow> innerShadows;
 private WeakHashMap<String, Pair<Canvas, Bitmap>> canvasStore;
 private Canvas tempCanvas;
 private Bitmap tempBitmap;
 private Drawable foregroundDrawable;
 private float strokeWidth;
 private Integer strokeColor;
 private Join strokeJoin;
 private float strokeMiter;
 private int[] lockedCompoundPadding;
 private boolean frozen = false;
 public MagicTextView(Context context) {
 super(context);
 init(null);
 }
 public MagicTextView(Context context, AttributeSet attrs) {
 super(context, attrs);
 init(attrs);
 }
 public MagicTextView(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 init(attrs);
 }
 public void init(AttributeSet attrs) {
 outerShadows = new ArrayList<Shadow>();
 innerShadows = new ArrayList<Shadow>();
 if (canvasStore == null) {
 canvasStore = new WeakHashMap<String, Pair<Canvas, Bitmap>>();
 }
 if (attrs != null) {
 TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MagicTextView);
 String typefaceName = a.getString(R.styleable.MagicTextView_typeface);
 if (typefaceName != null) {
 Typeface tf = Typeface.createFromAsset(getContext().getAssets(), String.format("fonts/%s.ttf", typefaceName));
 setTypeface(tf);
 }
 if (a.hasValue(R.styleable.MagicTextView_foreground)) {
 Drawable foreground = a.getDrawable(R.styleable.MagicTextView_foreground);
 if (foreground != null) {
 this.setForegroundDrawable(foreground);
 } else {
 this.setTextColor(a.getColor(R.styleable.MagicTextView_foreground, 0xff000000));
 }
 }
 if (a.hasValue(R.styleable.MagicTextView_innerShadowColor)) {
 this.addInnerShadow(a.getFloat(R.styleable.MagicTextView_innerShadowRadius, 0),
 a.getFloat(R.styleable.MagicTextView_innerShadowDx, 0),
 a.getFloat(R.styleable.MagicTextView_innerShadowDy, 0),
 a.getColor(R.styleable.MagicTextView_innerShadowColor, 0xff000000));
 }
 if (a.hasValue(R.styleable.MagicTextView_outerShadowColor)) {
 this.addOuterShadow(a.getFloat(R.styleable.MagicTextView_outerShadowRadius, 0),
 a.getFloat(R.styleable.MagicTextView_outerShadowDx, 0),
 a.getFloat(R.styleable.MagicTextView_outerShadowDy, 0),
 a.getColor(R.styleable.MagicTextView_outerShadowColor, 0xff000000));
 }
 if (a.hasValue(R.styleable.MagicTextView_strokeColor)) {
 float strokeWidth = a.getFloat(R.styleable.MagicTextView_strokeWidth, 1);
 int strokeColor = a.getColor(R.styleable.MagicTextView_strokeColor, 0xff000000);
 float strokeMiter = a.getFloat(R.styleable.MagicTextView_strokeMiter, 10);
 Join strokeJoin = null;
 switch (a.getInt(R.styleable.MagicTextView_strokeJoinStyle, 0)) {
 case (0):
 strokeJoin = Join.MITER;
 break;
 case (1):
 strokeJoin = Join.BEVEL;
 break;
 case (2):
 strokeJoin = Join.ROUND;
 break;
 }
 this.setStroke(strokeWidth, strokeColor, strokeJoin, strokeMiter);
 }
 }
 }
 public void setStroke(float width, int color, Join join, float miter) {
 strokeWidth = width;
 strokeColor = color;
 strokeJoin = join;
 strokeMiter = miter;
 }
 public void setStroke(float width, int color) {
 setStroke(width, color, Join.MITER, 10);
 }
 public void addOuterShadow(float r, float dx, float dy, int color) {
 if (r == 0) {
 r = 0.0001f;
 }
 outerShadows.add(new Shadow(r, dx, dy, color));
 }
 public void addInnerShadow(float r, float dx, float dy, int color) {
 if (r == 0) {
 r = 0.0001f;
 }
 innerShadows.add(new Shadow(r, dx, dy, color));
 }
 public void clearInnerShadows() {
 innerShadows.clear();
 }
 public void clearOuterShadows() {
 outerShadows.clear();
 }
 public void setForegroundDrawable(Drawable d) {
 this.foregroundDrawable = d;
 }
 public Drawable getForeground() {
 return this.foregroundDrawable == null ? this.foregroundDrawable : new ColorDrawable(this.getCurrentTextColor());
 }
 @Override
 public void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 freeze();
 Drawable restoreBackground = this.getBackground();
 Drawable[] restoreDrawables = this.getCompoundDrawables();
 int restoreColor = this.getCurrentTextColor();
 this.setCompoundDrawables(null, null, null, null);
 for (Shadow shadow : outerShadows) {
 this.setShadowLayer(shadow.r, shadow.dx, shadow.dy, shadow.color);
 super.onDraw(canvas);
 }
 this.setShadowLayer(0, 0, 0, 0);
 this.setTextColor(restoreColor);
 if (this.foregroundDrawable != null && this.foregroundDrawable instanceof BitmapDrawable) {
 generateTempCanvas();
 super.onDraw(tempCanvas);
 Paint paint = ((BitmapDrawable) this.foregroundDrawable).getPaint();
 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
 this.foregroundDrawable.setBounds(canvas.getClipBounds());
 this.foregroundDrawable.draw(tempCanvas);
 canvas.drawBitmap(tempBitmap, 0, 0, null);
 tempCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
 }
 if (strokeColor != null) {
 TextPaint paint = this.getPaint();
// paint.setTextAlign(Paint.Align.CENTER);
 paint.setStyle(Style.STROKE);
 paint.setStrokeJoin(strokeJoin);
 paint.setStrokeMiter(strokeMiter);
 this.setTextColor(strokeColor);
 paint.setStrokeWidth(strokeWidth);
 super.onDraw(canvas);
 paint.setStyle(Style.FILL);
 this.setTextColor(restoreColor);
 }
 if (innerShadows.size() > 0) {
 generateTempCanvas();
 TextPaint paint = this.getPaint();
 for (Shadow shadow : innerShadows) {
 this.setTextColor(shadow.color);
 super.onDraw(tempCanvas);
 this.setTextColor(0xFF000000);
 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
 paint.setMaskFilter(new BlurMaskFilter(shadow.r, BlurMaskFilter.Blur.NORMAL));
 tempCanvas.save();
 tempCanvas.translate(shadow.dx, shadow.dy);
 super.onDraw(tempCanvas);
 tempCanvas.restore();
 canvas.drawBitmap(tempBitmap, 0, 0, null);
 tempCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
 paint.setXfermode(null);
 paint.setMaskFilter(null);
 this.setTextColor(restoreColor);
 this.setShadowLayer(0, 0, 0, 0);
 }
 }
 if (restoreDrawables != null) {
 this.setCompoundDrawablesWithIntrinsicBounds(restoreDrawables[0], restoreDrawables[1], restoreDrawables[2], restoreDrawables[3]);
 }
 this.setBackgroundDrawable(restoreBackground);
 this.setTextColor(restoreColor);
 unfreeze();
 }
 private void generateTempCanvas() {
 String key = String.format("%dx%d", getWidth(), getHeight());
 Pair<Canvas, Bitmap> stored = canvasStore.get(key);
 if (stored != null) {
 tempCanvas = stored.first;
 tempBitmap = stored.second;
 } else {
 tempCanvas = new Canvas();
 tempBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
 tempCanvas.setBitmap(tempBitmap);
 canvasStore.put(key, new Pair<Canvas, Bitmap>(tempCanvas, tempBitmap));
 }
 }
 public void freeze() {
 lockedCompoundPadding = new int[]{
 getCompoundPaddingLeft(),
 getCompoundPaddingRight(),
 getCompoundPaddingTop(),
 getCompoundPaddingBottom()
 };
 frozen = true;
 }
 public void unfreeze() {
 frozen = false;
 }
 @Override
 public void requestLayout() {
 if (!frozen) super.requestLayout();
 }
 @Override
 public void postInvalidate() {
 if (!frozen) super.postInvalidate();
 }
 @Override
 public void postInvalidate(int left, int top, int right, int bottom) {
 if (!frozen) super.postInvalidate(left, top, right, bottom);
 }
 @Override
 public void invalidate() {
 if (!frozen) super.invalidate();
 }
 @Override
 public void invalidate(Rect rect) {
 if (!frozen) super.invalidate(rect);
 }
 @Override
 public void invalidate(int l, int t, int r, int b) {
 if (!frozen) super.invalidate(l, t, r, b);
 }
 @Override
 public int getCompoundPaddingLeft() {
 return !frozen ? super.getCompoundPaddingLeft() : lockedCompoundPadding[0];
 }
 @Override
 public int getCompoundPaddingRight() {
 return !frozen ? super.getCompoundPaddingRight() : lockedCompoundPadding[1];
 }
 @Override
 public int getCompoundPaddingTop() {
 return !frozen ? super.getCompoundPaddingTop() : lockedCompoundPadding[2];
 }
 @Override
 public int getCompoundPaddingBottom() {
 return !frozen ? super.getCompoundPaddingBottom() : lockedCompoundPadding[3];
 }
 public static class Shadow {
 float r;
 float dx;
 float dy;
 int color;

 public Shadow(float r, float dx, float dy, int color) {
 this.r = r;
 this.dx = dx;
 this.dy = dy;
 this.color = color;
 }
 }
}

Github: https://github.com/345166018/AndroidUI/tree/master/HxZhibo
총결산
위 에서 말 한 것 은 편집장 이 소개 한 안 드 로 이 드 모방 라 이브 앱 선물 기능 입 니 다.도움 이 되 셨 으 면 좋 겠 습 니 다!

좋은 웹페이지 즐겨찾기