Chế độ xem trung tâm Android trong FrameLayout không hoạt động


83

Tôi có FrameLayout trong đó tôi có 2 điều khiển: - chế độ xem tùy chỉnh vẽ hình ảnh và một số văn bản trên đó - chế độ xem văn bản có văn bản

Tôi muốn căn giữa cả hai trong FrameLayout nhưng tôi không thể làm được. Texview được căn giữa tốt, chế độ xem cusom của tôi vẫn ở bên trái, khi tôi làm cho nó hiển thị.

<FrameLayout android:id="@+id/CompassMap"
               android:layout_width="fill_parent" 
               android:layout_height="wrap_content"
               android:layout_weight="1"
               android:gravity="center">

             <view class="com.MyView"
        android:id="@+id/myView"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|center_horizontal"
        android:visibility="gone"/>

                <TextView android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|center_horizontal"
        android:text="CENTERED" /> 
</FrameLayout>

Đối với Mathias, tôi không làm bất cứ điều gì trong hàm tạo, nó chỉ đơn giản

   public class MyMapView extends View {

private int xPos = 0; 
private int yPos = 0;
private Bitmap trackMap;

private Matrix backgroundMatrix;
private Paint backgroundPaint;

private Bitmap position;
private Matrix positionMatrix;
private Paint positionPaint;

public MyMapView(Context context) {
    super(context);
    init(context, null);
}

public MyMapView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context, attrs);
}

public MyMapView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context, attrs);
}

private void init(final Context context, AttributeSet attrs) {

backgroundMatrix = new Matrix();
backgroundPaint = new Paint();
backgroundPaint.setFilterBitmap(true);

position = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.position);
positionMatrix = new Matrix();

positionPaint = new Paint();
positionPaint.setFilterBitmap(true);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
}

@Override
protected void onDraw(Canvas canvas) {

    int width = getMeasuredWidth();
    int height = getMeasuredHeight();

    if (trackMap!=null)
    {
        Bitmap resizedBitmap = Bitmap.createScaledBitmap(trackMap, height, height, true);
        canvas.drawBitmap(resizedBitmap, backgroundMatrix, backgroundPaint);

    }

        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        canvas.translate(xPos-position.getWidth()/2, yPos-position.getHeight()/2);
        canvas.drawBitmap(position, positionMatrix, positionPaint);

        canvas.restore();
}

    public void updatePosition(int xpos, int ypos, Bitmap trackImage)
    {
        xPos=xpos;
        yPos=ypos;
        trackMap = trackImage;
        invalidate();
    }
}

1
Chế độ xem tùy chỉnh của bạn được mở rộng từ đâu? Chắc chắn bạn đang xử lý các tham số trong hàm tạo của mình?
Mathias Conradt 29/10/10

Có lý do đặc biệt nào khiến bạn phải sử dụng FrameLayout và TextView có được hiển thị trên đầu View không?
Octavian A. Damiean,

1
Vâng, FrameLayout sẽ không cho phép bạn làm điều đó. Nó thực sự chỉ để giữ một góc nhìn duy nhất. Nếu bạn thêm vào nó nhiều hơn nó sẽ có hành vi chính xác mà bạn đang đề cập, nó chỉ cần thêm các phần tử trong một ngăn xếp dọc bằng cách ghim vào phía trên bên trái. developer.android.com/reference/android/widget/FrameLayout.html
trơnjimbo

Câu trả lời:


42

Tôi đề xuất một RelativeLayout thay vì FrameLayout.

Giả sử rằng bạn muốn luôn có TextView bên dưới ImageView, tôi sẽ sử dụng bố cục sau.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/imageview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerInParent="true"
        android:src="@drawable/icon"
        android:visibility="visible"/>
    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_below="@id/imageview"
        android:gravity="center"
        android:text="@string/hello"/>
</RelativeLayout>

Lưu ý rằng nếu bạn đặt visibilitycủa một phần tử thành gonethì không gian mà phần tử đó sẽ sử dụng sẽ biến mất trong khi khi bạn sử dụng invisiblethay vào đó, không gian mà phần tử sử dụng sẽ được giữ nguyên.

Nếu bạn muốn có TextView ở trên ImageView thì bạn chỉ cần loại bỏ android:layout_alignParentTophoặc đặt nó thành falsevà trên TextView thì loại bỏ android:layout_below="@id/imageview"thuộc tính. Như thế này.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/imageview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="false"
        android:layout_centerInParent="true"
        android:src="@drawable/icon"
        android:visibility="visible"/>
    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:text="@string/hello"/>
</RelativeLayout>

Tôi hy vọng đó là điều mà bạn đang tìm kiếm.


Lời giải thích của bạn có vẻ rất tốt và nó sẽ hoạt động trong trường hợp của tôi, nhưng nó không. Trong RelativeLayout của tôi, tôi có nhiều hơn những gì tôi đã nói: 2 chế độ xem tùy chỉnh, một LinearLayout, một Nút và một TextView. Điều tò mò là mọi thứ đều hoạt động tốt với chế độ xem tùy chỉnh của tôi. Chế độ xem tùy chỉnh khác không bị ảnh hưởng vì nó là thuộc tính fill_parent. Nhưng, tôi đang cố gắng xem liệu mình có bỏ lỡ quá trình hình thành hay không. Cảm ơn bạn.
Alin

Mục đích của chế độ xem tùy chỉnh của bạn là gì?
Octavian A. Damiean

Tôi đã thêm toàn bộ mã của chế độ xem tùy chỉnh vào câu hỏi. Về cơ bản, vẽ một hình lớn làm nền và một hình nhỏ hơn ở vị trí x, y.
Alin

Điều này chỉ hoạt động như mong đợi nếu bạn chỉ định một src cho ImageView của mình. Nếu bạn đang cố gắng đặt văn bản (hoặc các nút hoặc bất cứ thứ gì) bên dưới ImageView sẽ được điền vào sau này, bạn sẽ gặp một số rắc rối vì bạn sẽ không thể biết kích thước các nút của mình hoặc bất cứ thứ gì cho đến sau onResume ( ) đã hoàn thành.

4
Bạn muốn tránh RelativeLayouts nếu có thể. Mỗi RelativeLayout yêu cầu 2 lần đo - do đó, RelativeLayout lồng nhau có thời gian đo theo cấp số nhân. Mỗi lần bạn thêm một RelativeLayout lồng nhau mới, thời gian đo của bạn sẽ tăng gấp đôi.
Martin Konecny

384

Chúng ta có thể căn chỉnh chế độ xem ở giữa FrameLayoutbằng cách đặt layout_gravitychế độ xem con.

Trong XML:

android:layout_gravity="center"

Trong mã Java:

FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;

Lưu ý: FrameLayout.LayoutParamskhông sử dụng LayoutParams hiện có khác


107
Đây phải là câu trả lời được chấp nhận. Người còn lại thay đổi câu hỏi hơn là trả lời nó.
Muz

Y, giải pháp này không phù hợp với tôi. Thêm Imageview vào giữa Frame layout.cap = new ImageView (CameraActivity.this); LayoutParams params2 = new LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params2.gravity = Gravity.CENTER; cap.setLayoutParams (params2); cameraView.addView (cap);
Akanksha Rathore,

8
Bây giờ nó đã làm việc cho tôi. Lỗi của tôi là tôi đã nhập sai gói. Sau 4 giờ, tôi đã nhầm rằng gói Thực tế nên nhập là android.widget.FrameLayout.LayoutParams;
Akanksha Rathore,

2
@Akanksha đó là câu trả lời đúng duy nhất :) các bạn phải sử dụng FrameLayout.LayoutParams để căn giữa một khung nhìn vào FrameLayout.
hrules6872,

5

Chỉ cần làm theo thứ tự này

Bạn có thể căn giữa bất kỳ số lượng trẻ nào trong a FrameLayout.

<FrameLayout
    >
    <child1
        ....
        android:layout_gravity="center"
        .....
        />
    <Child2
        ....
        android:layout_gravity="center"
        />
</FrameLayout>

Vì vậy, chìa khóa là

thêm android:layout_gravity="center"vào các chế độ xem con.

Ví dụ:

Tôi làm trung tâm một CustomView và một TextView trên FrameLayoutnhư thế này

Mã:

<FrameLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >
    <com.airbnb.lottie.LottieAnimationView
        android:layout_width="180dp"
        android:layout_height="180dp"
        android:layout_gravity="center"
        app:lottie_fileName="red_scan.json"
        app:lottie_autoPlay="true"
        app:lottie_loop="true" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textColor="#ffffff"
        android:textSize="10dp"
        android:textStyle="bold"
        android:padding="10dp"
        android:text="Networks Available: 1\n click to see all"
        android:gravity="center" />
</FrameLayout>

Kết quả:

nhập mô tả hình ảnh ở đây


1
Đây là câu trả lời duy nhất phù hợp với tôi. Tôi có một FrameLayoutcái chứa một TextureViewvà hai SurfaceView. Với điều này (và setZOrderOnTop(true);trên các Bề mặt tôi cuối cùng đã tập trung tất cả lớp phủ ở giữa
Xavi

1

Đặt 'center_horizontal' và 'center_vertical' hoặc chỉ 'center' của thuộc tính layout_gravity của tiện ích con

    <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MovieActivity"
    android:id="@+id/mainContainerMovie"
    >


    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#3a3f51b5"
       />

    <ProgressBar
        android:id="@+id/movieprogressbar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|center_horizontal" />
</FrameLayout>

0

Để căn giữa một chế độ xem trong Framelayout, có một số thủ thuật có sẵn. Đơn giản nhất tôi đã sử dụng cho Chế độ xem web và Thanh tiến trình của mình (rất giống với bố cục hai đối tượng của bạn), tôi vừa thêmandroid:layout_gravity="center"

Đây là XML hoàn chỉnh trong trường hợp nếu ai đó cần điều tương tự để làm

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".WebviewPDFActivity"
    android:layout_gravity="center"
    >
    <WebView
        android:id="@+id/webView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"

        />
    <ProgressBar
        android:id="@+id/progress_circular"
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:visibility="visible"
        android:layout_gravity="center"
        />


</FrameLayout>

Đây là đầu ra của tôi

ảnh chụp màn hình

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.