Android 동적 퍼 지 효 과 를 빠르게 실현 하 는 방법 을 알려 드 립 니 다.

머리말
야후 날씨의 화면 이 미 끄 러 울 때 배경 사진 이 따라 이동 합 니 다.가장 중요 한 것 은 배경 사진 이 손가락 상하 로 이동 하 는 거리 에 따라 어느 정도 모호 해 지 는 것 입 니 다.놀 랍 습 니 다.안 드 로 이 드 플랫폼 에서 모호 한 렌 더 링 을 하 는 것 은 CPU 도 상당히 소모 되 고 시간 도 많이 걸 리 는 작업 이라는 것 을 잘 처리 하지 못 하면 카드 가 걸 리 는 것 을 피 할 수 없습니다.
일반적으로 효율 을 고려 하여 한 장의 그림 을 과장 하 는 가장 좋 은 방법 은 사용OpenGL이 고,그 다음은 C+/C 를 사용 하 며,자바 코드 를 사용 하 는 것 이 가장 느리다.그러나 안 드 로 이 드 가 출시RenderScript된 후에 우 리 는 새로운 선택 이 생 겼 다.테스트 에 따 르 면 사용RenderScript의 렌 더 링 효율 은 C/C++를 사용 하 는 것 과 막상막하 이지 만 사용RenderScript은 사용JNI보다 훨씬 간단 하 다.이와 함께 안 드 로 이 드 팀 은 낮은 버 전의 안 드 로 이 드 플랫폼 에서 도 사용 할 수 있 도록RenderScript지원 라 이브 러 리 를 제공 했다.
그러나 사용RenderScript하기 전에 한 장의 그림 을 모호 하 게 하 는 데 주의해 야 할 것 은 우 리 는 원래 의 사이즈 해상 도 를 가 진 그림 을 사용 하지 말고 그림 의 비율 을 줄 이 는 것 이 좋 습 니 다.이 작은 렌 더 링 의 효율 이 높 습 니 다.
동적 모호 한 실현
어떻게RenderScript을 사용 하여 그림 한 장 을 모호 하 게 합 니까?쓸데없는 말 은 그만 하고 핵심 코드 부터 올 려 라.

public class BlurBitmap {
 /**
  *       
  */
 private static final float BITMAP_SCALE = 0.4f;
 /**
  *      ( 0.0 25.0  )
  */
 private static final float BLUR_RADIUS = 25f;
 
 /**
  *          
  *
  * @param context      
  * @param image         
  * @return           
  */
 public static Bitmap blur(Context context, Bitmap image) {
  //           
  int width = Math.round(image.getWidth() * BITMAP_SCALE);
  int height = Math.round(image.getHeight() * BITMAP_SCALE);
 
  //                。
  Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
  //             。
  Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
 
  //   RenderScript    
  RenderScript rs = RenderScript.create(context);
  //          RenderScript     
  ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
 
  //   RenderScript     VM     ,      Allocation           。
  //   Allocation            ,    copyTo()       。
  Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
  Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
 
  //          , 25f      
  blurScript.setRadius(BLUR_RADIUS);
  //   blurScript       
  blurScript.setInput(tmpIn);
  //              
  blurScript.forEach(tmpOut);
 
  //       Allocation 
  tmpOut.copyTo(outputBitmap);
 
  return outputBitmap;
 }
}
위의 코드 를 완성 한 후 app 의 gradle 파일 에 다음 과 같은 지원 을 추가 해 야 합 니 다.

 defaultConfig {
 ......
 renderscriptTargetApi 19
 renderscriptSupportModeEnabled true
}
코드 는 이 해 를 돕 기 위해 간단 한 주석 을 달 았 습 니 다.상세 한 이해 가 필요 하 다 면 공식 문 서 를 찾 아 볼 수 있 습 니 다.
그리고 우 리 는 모호 전과 모호 후의 효과 대 비 를 볼 수 있다.

그림 을 모호 하 게 한 다음 에 동적 모호 효 과 를 어떻게 실현 하 는 지 고려 해 야 한다.한 가지 주의해 야 할 것 은 우리 가RenderScript이라는 효율 적 인 렌 더 링 방식 을 사용 하 더 라 도 실제 테스트 에서 500*700 해상도 의 PNG 형식 그림 을 렌 더 링 하 는 것 은 나의 Pro 6 핸드폰 에서 50ms 정도 의 시간 이 필요 하 다 는 것 이다.분명히 위의 코드 를 사용 하여 실시 간 으로 렌 더 링 을 하면 인터페이스 가 심각하게 끊 길 수 있다.
이 길이 통 하지 않 는 다 는 것 을 실시 간 으로 보 여 주 는 이상 우 리 는 다른 길 을 개척 해 야 한다.나 는 그림 을 최대한 모호 하 게 처리 한 다음 에 원 도 를 모호 한 그림 위 에 놓 고 원 도의 투명 도(Alpha 값)를 계속 바 꾸 어 동태 적 인 모호 효 과 를 실현 하 는 방법 을 제공 할 수 있다.
간단 한 코드 는 다음 과 같 습 니 다.

public class MainActivity extends AppCompatActivity {
 
 /**
  *       
  */
 private ImageView mOriginImg;
 
 /**
  *         
  */
 private ImageView mBluredImage;
 
 /**
  *    SeekBar
  */
 private SeekBar mSeekBar;
 
 /**
  *        
  */
 private TextView mProgressTv;
 
 /**
  *    
  */
 private int mAlpha;
 
 /**
  *     
  */
 private Bitmap mTempBitmap;
 
 /**
  *       
  */
 private Bitmap mFinalBitmap;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
 
  //      
  initViews();
 
  //     
  mTempBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dayu);
  mFinalBitmap = BlurBitmap.blur(this, mTempBitmap);
 
  //            
  mBluredImage.setImageBitmap(mFinalBitmap);
  mOriginImg.setImageBitmap(mTempBitmap);
 
  //   seekbar    
  setSeekBar();
 }
 
 /**
  *      
  */
 private void initViews() {
  mBluredImage = (ImageView) findViewById(R.id.activity_main_blured_img);
  mOriginImg = (ImageView) findViewById(R.id.activity_main_origin_img);
  mSeekBar = (SeekBar) findViewById(R.id.activity_main_seekbar);
  mProgressTv = (TextView) findViewById(R.id.activity_main_progress_tv);
 }
 
 /**
  *   seekbar    
  */
 private void setSeekBar() {
  mSeekBar.setMax(100);
  mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
   @Override
   public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    mAlpha = progress;
    mOriginImg.setAlpha((int) (255 - mAlpha * 2.55));
    mProgressTv.setText(String.valueOf(mAlpha));
   }
 
   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {
 
   }
 
   @Override
   public void onStopTrackingTouch(SeekBar seekBar) {
 
   }
  });
 }
}
xml 레이아웃 파일 코드 는 다음 과 같 습 니 다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:id="@+id/activity_main"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 
 <FrameLayout
  android:layout_width="match_parent"
  android:layout_weight="1"
  android:layout_height="0dp">
 
  <ImageView
   android:id="@+id/activity_main_blured_img"
   android:scaleType="centerCrop"
   android:src="@drawable/dayu"
   android:layout_width="match_parent"
   android:layout_height="match_parent"/>
 
  <ImageView
   android:id="@+id/activity_main_origin_img"
   android:scaleType="centerCrop"
   android:layout_width="match_parent"
   android:layout_height="match_parent"/>
 </FrameLayout>
 
 <LinearLayout
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="80dp">
 
  <SeekBar
   android:layout_marginTop="@dimen/activity_vertical_margin"
   android:id="@+id/activity_main_seekbar"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_marginLeft="16dp"
   android:layout_marginRight="16dp"/>
 
  <TextView
   android:id="@+id/activity_main_progress_tv"
   android:text="0"
   android:textSize="24sp"
   android:layout_gravity="center"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>
 </LinearLayout>
 
</LinearLayout>
효 과 는 다음 과 같 습 니 다:

어때요?너무 쉬 운 모습 아니 야?퍼 지 처리 방법 만 호출 하고 SeekBar 의 미끄럼 감청 에서 원 이미지setAlpha()방법 을 호출 하여 동적 퍼 지 효 과 를 실현 해 야 합 니 다.
이게 끝 인 줄 알 아?아니 야,아니 야.우리 의 목적 은 이렇게 단순 한 것 이 아니 야.아,아니 야,그렇게 간단 한 것 이 아니 야.글 시작 할 때 얘 기 했 던 거 기억 나 세 요?우리 의 최종 목적 은 야후 날씨의 인터페이스 효 과 를 간단하게 모방 하 는 것 이다.
야후 날씨 창 모방
위의 기초 가 있 으 면 야후 날씨의 인터페이스 효 과 를 쉽게 모방 할 수 있다.쉽게 말 하면 위 에서 만 든 효 과 를 바탕 으로 다음 과 같은 두 가지 주의해 야 할 점 이 있다.
미끄럼 사건 을 감청 한 다음 배경 그림 호출setTop()방법 으로 그림 을 위로 이동 시 켜 야 합 니 다.
그림 을 위로 이동 하려 면 그림 의 높이 를 수 동 으로 늘 려 야 합 니 다.그렇지 않 으 면 그림 이 위로 이동 한 후에 바닥 에 흰색 이 남 을 것 입 니 다.그림 높이 를 설정 하 는 핵심 코드 는 다음 과 같 습 니 다.

WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point point = new Point();
display.getSize(point);
//    ImageView   
int height = point.y;
ViewGroup.LayoutParams params = imageView.getLayoutParams();
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
//  ImageView     100
params.height = height + 100;
//       
imageView.requestLayout();
위의 두 가지 내용 을 완성 하면 야후 날씨의 첫 페이지 를 기본적으로 흉 내 낼 수 있다.
첫 번 째 예 를 결합 한 demo 의 효 과 는 다음 과 같다.

총결산
이상 이 바로 본문의 전체 내용 입 니 다.실현 후의 효 과 는 매우 좋 지 않 습 니까?관심 있 는 친 구 는 빨리 스스로 조작 하 세 요.본 고 는 여러분 이 안 드 로 이 드 를 개발 하 는 데 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기