내 안드로이드 프로젝트의 모든 요소를 동적으로 만들고 있습니다. 버튼의 너비와 높이를 얻으려고 노력하여 버튼을 회전시킬 수 있습니다. 안드로이드 언어로 작업하는 법을 배우려고합니다. 그러나 0을 반환합니다.
나는 약간의 연구를했는데 onCreate()
방법 이외의 다른 곳에서 수행해야한다는 것을 알았습니다 . 누군가 나에게 그것을하는 방법에 대한 예를 줄 수 있다면 좋을 것입니다.
내 현재 코드는 다음과 같습니다.
package com.animation;
import android.app.Activity;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.Button;
import android.widget.LinearLayout;
public class AnimateScreen extends Activity {
//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout ll = new LinearLayout(this);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(30, 20, 30, 0);
Button bt = new Button(this);
bt.setText(String.valueOf(bt.getWidth()));
RotateAnimation ra = new RotateAnimation(0,360,bt.getWidth() / 2,bt.getHeight() / 2);
ra.setDuration(3000L);
ra.setRepeatMode(Animation.RESTART);
ra.setRepeatCount(Animation.INFINITE);
ra.setInterpolator(new LinearInterpolator());
bt.startAnimation(ra);
ll.addView(bt,layoutParams);
setContentView(ll);
}
도움을 주시면 감사하겠습니다.
답변
getWidth()
너무 일찍 전화하고 있습니다. UI 크기는 아직 화면에 표시되지 않았습니다.
어쨌든 당신이하고있는 일을하고 싶을 것입니다. 애니메이션되는 위젯은 클릭 가능한 영역을 변경하지 않으므로 버튼은 회전 방식에 관계없이 원래 방향으로 클릭에 응답합니다.
즉, 차원 리소스 를 사용하여 단추 크기를 정의한 다음이 문제를 방지하기 위해 레이아웃 파일과 소스 코드에서 해당 차원 리소스를 참조 할 수 있습니다.
답변
기본적인 문제는 (특히 같은 동적 값과 실제 측정 도면 상 기다릴 필요가 있다는 것입니다 wrap_content
또는 match_parent
), 그러나 보통이 단계까지 완료되지 않았습니다 onResume()
. 따라서이 단계를 기다리는 데 필요한 해결 방법이 필요합니다. 이에 대한 다른 가능한 해결책이 있습니다.
1. 그리기 / 레이아웃 이벤트 듣기 : ViewTreeObserver
다른 그리기 이벤트에 대해 ViewTreeObserver가 시작됩니다. 일반적으로 OnGlobalLayoutListener
측정을 위해 원하는 것이므로 리스너의 코드가 레이아웃 단계 후에 호출되므로 측정이 준비됩니다.
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
view.getHeight(); //height is ready
}
});
참고 : 리스너는 모든 레이아웃 이벤트에서 실행되므로 즉시 리스너가 제거됩니다. SDK Lvl <16 앱을 지원해야하는 경우 이를 사용하여 리스너를 등록 취소하십시오.
public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)
2. 레이아웃 대기열에 Runnable을 추가합니다 : View.post ()
잘 알려지지 않은 솔루션과 내가 가장 좋아하는 솔루션. 기본적으로 View의 post 메소드를 자신의 실행 파일과 함께 사용하십시오. 기본적으로 Romain Guy가 말한 것처럼 뷰의 측정, 레이아웃 등 후에 코드를 큐 에 넣습니다 .
UI 이벤트 큐는 이벤트를 순서대로 처리합니다. setContentView ()가 호출 된 후 이벤트 큐에는 릴레이를 요청하는 메시지가 포함되므로 큐에 게시하는 모든 것은 레이아웃 패스 후 발생합니다.
예:
final View view=//smth;
...
view.post(new Runnable() {
@Override
public void run() {
view.getHeight(); //height is ready
}
});
장점 ViewTreeObserver
:
- 코드는 한 번만 실행되며 실행 후 관찰자를 비활성화 할 필요가 없으므로 번거로울 수 있습니다
- 덜 장황한 구문
참고 문헌 :
3. 뷰의 onLayout 메소드 덮어 쓰기
이것은 로직이 뷰 자체에 캡슐화 될 수있는 특정 상황에서만 실용적입니다. 그렇지 않으면 매우 장황하고 성가신 구문입니다.
view = new View(this) {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
view.getHeight(); //height is ready
}
};
또한 onLayout은 여러 번 호출되므로 메소드에서 수행 한 작업을 고려하거나 처음으로 코드를 비활성화하십시오.
4. 레이아웃 단계를 거쳤는지 확인
UI를 작성하는 동안 여러 번 실행되는 코드가있는 경우 다음 지원 v4 lib 메소드를 사용할 수 있습니다.
View viewYouNeedHeightFrom = ...
...
if(ViewCompat.isLaidOut(viewYouNeedHeightFrom)) {
viewYouNeedHeightFrom.getHeight();
}
뷰가 창에 마지막으로 연결되거나 분리 된 후 하나 이상의 레이아웃을 통과 한 경우 true를 리턴합니다.
추가 : 정적으로 정의 된 측정 값 얻기
정적으로 정의 된 높이 / 너비를 얻는 것으로 충분하다면 다음과 같이하면됩니다.
그러나 이것은 드로잉 후 실제 너비 / 높이와 다를 수 있습니다. javadoc은 차이점을 완벽하게 설명합니다.
뷰의 크기는 너비와 높이로 표시됩니다. 뷰에는 실제로 두 쌍의 너비 및 높이 값이 있습니다.
첫 번째 쌍은 측정 된 너비와 측정 된 높이라고합니다. 이러한 차원은 뷰가 부모 내에 얼마나 큰지를 정의합니다 (자세한 내용은 레이아웃 참조). getMeasuredWidth () 및 getMeasuredHeight ()를 호출하여 측정 된 차원을 얻을 수 있습니다.
두 번째 쌍은 단순히 너비와 높이 또는 때때로 그리기 너비와 그리기 높이라고합니다. 이러한 치수는 도면 시간과 배치 후 화면에서 실제보기 크기를 정의합니다. 이 값들은 측정 된 폭과 높이와 다를 수 있지만 반드시 그런 것은 아닙니다. 너비와 높이는 getWidth () 및 getHeight ()를 호출하여 얻을 수 있습니다.
답변
사용할 수있다
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
//Here you can get the size!
}
답변
이 솔루션을 사용했는데 onWindowFocusChanged ()보다 낫습니다. DialogFragment를 연 다음 전화를 돌리면 사용자가 대화 상자를 닫을 때만 onWindowFocusChanged가 호출됩니다.
yourView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// Ensure you call it only once :
yourView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
// Here you can get the size :)
}
});
편집 : removeGlobalOnLayoutListener가 사용되지 않으므로 이제 다음을 수행하십시오.
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {
// Ensure you call it only once :
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
yourView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
else {
yourView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
// Here you can get the size :)
}
답변
Ian 이이 Android Developers 스레드 에서 언급했듯이 :
어쨌든, 모든 요소가 구성되고 부모 뷰에 추가 된 후 창의 내용 레이아웃이 발생
합니다. View에 포함 된 구성 요소와 그 구성 요소 등을 알 때까지 배치 할 수있는 합리적인 방법이 없기 때문에이 방식이어야합니다.결론적으로 생성자에서 getWidth () 등을 호출하면 0이 반환됩니다. 절차는 생성자에서 모든 뷰 요소를 생성 한 다음 뷰의 onSizeChanged () 메소드가 호출 될 때까지 기다리는 것입니다. 즉, 실제 크기를 처음 찾을 때가되므로 GUI 요소의 크기를 설정할 때입니다.
onSizeChanged ()는 때때로 0의 매개 변수로 호출됩니다.이 경우를 확인하고 즉시 반환하십시오 (그래서 레이아웃 등을 계산할 때 0으로 나누지 않습니다). 얼마 후 실제 값으로 호출됩니다.
답변
화면에 표시되기 전에 일부 위젯의 너비를 가져와야하는 경우 getMeasuredWidth () 또는 getMeasuredHeight ()를 사용할 수 있습니다.
myImage.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
int width = myImage.getMeasuredWidth();
int height = myImage.getMeasuredHeight();
답변
나는 다른 청취자보다 조금 일찍 호출되기 때문에 OnPreDrawListener()
대신에 오히려 사용하고 싶습니다 addOnGlobalLayoutListener()
.
view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
{
@Override
public boolean onPreDraw()
{
if (view.getViewTreeObserver().isAlive())
view.getViewTreeObserver().removeOnPreDrawListener(this);
// put your code here
return true;
}
});