Thanh tiến trình trong Thanh hành động


79

Tóm tắt câu hỏi: Làm cách nào để tôi có thể ProgressBartích hợp bên trong ActionBar, như trên Ứng dụng Chrome?

Chi tiết: Xem ảnh chụp màn hình này từ Chrome:

Ảnh chụp màn hình Chrome dành cho Android

Tôi muốn tạo một Thanh hành động giống như thế này. Ngay dưới Thanh tác vụ, có một Thanh tiến trình lấp đầy theo tải trang. Tôi đã xem ví dụ này từ nhiều ứng dụng, như Feedly, nhưng tôi chưa thể tạo triển khai của riêng mình. Tôi đã thử sử dụng các API riêng của Android để tạo nó:

@Override
protected void onCreate(Bundle savedInstanceState) {
    //Request Permission to display the Progress Bar...
    this.requestWindowFeature(Window.FEATURE_PROGRESS);
            this.setWindowContentView(R.layout.activity_main)
    super.onCreate(savedInstanceState);

    this.setProgressBarIndeterminate(true);
}

Nhưng mã này chỉ làm cho Thanh tiến trình hiển thị trên Thanh tác vụ, như sau:

Ảnh chụp màn hình ứng dụng của tôi

Vì vậy, làm cách nào để làm cho Thanh tiến trình của tôi xuất hiện dưới Thanh tác vụ, như trên Ứng dụng Chrome?


câu hỏi có thể trùng lặp của câu trả lời này: stackoverflow.com/a/10755545/794088
petey

bạn đã tìm ra giải pháp chưa
Eric

ảnh chụp màn hình cho bà tôi
IlyaEremin

Câu trả lời:


7

Đây hiện là một hành vi gốc có thể đạt được bằng SwipeRefreshLayout .

Bạn có thể bao bọc chế độ xem có thể cuộn của mình bằng một SwipeRefreshLayoutvà sau đó bạn chỉ cần nghe các sự kiện onRefresh :

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
    swipeLayout.setOnRefreshListener(this);
    swipeLayout.setColorScheme(android.R.color.holo_blue_bright, 
            android.R.color.holo_green_light, 
            android.R.color.holo_orange_light, 
            android.R.color.holo_red_light);
}


@Override public void onRefresh() {
    new Handler().postDelayed(new Runnable() {
        @Override public void run() {
            swipeLayout.setRefreshing(false);
        }
    }, 5000);
}

Một hướng dẫn hay và đơn giản có thể được tìm thấy trong blog này .


56

Tôi không hoàn toàn hài lòng với câu trả lời được chấp nhận ở trên, vì vậy tôi đã tự mình nghiên cứu thêm.

Mẹo mà tôi tin rằng họ đã sử dụng là họ truy xuất chế độ xem trên cùng trong hệ thống phân cấp chế độ xem được gọi DecorViewvà thêm thanh tiến trình vào đó. Bằng cách đó, thanh tiến trình hiển thị cả trên thanh tác vụ VÀ khu vực nội dung. Lưu ý rằng câu trả lời của SD đặt thanh tiến trình vào vùng nội dung và 'đánh cắp' không gian khỏi nội dung thực tế, điều này có thể dẫn đến kết quả không mong muốn.

Ảnh chụp màn hình mẫu của việc triển khai này:

Thanh tiến trình

ProgressBarIndetermina

Chỉ cần đặt mã này vào onCreatephương thức của một số hoạt động và nó sẽ hoạt động:

// create new ProgressBar and style it
final ProgressBar progressBar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);
progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 24));
progressBar.setProgress(65);

// retrieve the top view of our application
final FrameLayout decorView = (FrameLayout) getWindow().getDecorView();
decorView.addView(progressBar);

// Here we try to position the ProgressBar to the correct position by looking
// at the position where content area starts. But during creating time, sizes 
// of the components are not set yet, so we have to wait until the components
// has been laid out
// Also note that doing progressBar.setY(136) will not work, because of different
// screen densities and different sizes of actionBar
ViewTreeObserver observer = progressBar.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        View contentView = decorView.findViewById(android.R.id.content);
        progressBar.setY(contentView.getY() - 10);

        ViewTreeObserver observer = progressBar.getViewTreeObserver();
        observer.removeOnGlobalLayoutListener(this);
    }
});

Bạn có thể sử dụng đối số chiều cao của LayoutParams để đặt ProgressBar rộng hơn hoặc hẹp hơn, nhưng bạn có thể phải điều chỉnh độ -10lệch.

Tạo kiểu

Thật không may, bạn có thể thấy nền xám xấu xí của thanh tiến trình. Để loại bỏ nó, chỉ cần tìm kiếm nền theo id và cố gắng ẩn nó không hoạt động. Để loại bỏ nền, tôi phải tạo bộ kéo giống hệt phiên bản hệ thống và xóa mục nền.

TL; DR: Tạo tệp progress_horizontal_holo_no_background_light.xmlvà dán tệp có thể vẽ này:

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

    <item android:id="@android:id/secondaryProgress">
        <scale android:scaleWidth="100%"
               android:drawable="@drawable/progress_secondary_holo_light" />
    </item>

    <item android:id="@android:id/progress">
        <scale android:scaleWidth="100%"
               android:drawable="@drawable/progress_primary_holo_light" />
    </item>

</layer-list>

Sao chép các tệp có thể kéo .png thích hợp từ sdk/platforms/android-xx/data/res/drawable-xxx/dự án của bạn và sau đó trong mã, bạn có thể thêm:

progressBar.setProgressDrawable(getResources().getDrawable(R.drawable.progress_horizontal_holo_no_background_light));

Thêm: Thanh tiến trình không xác định

Phiên bản Pre-KitKat của thanh tiến trình không xác định khá xấu và chậm. Bạn có thể tải xuống tiến trình mượt mà mới được gọi ButteryProgressBar. Chỉ cần tìm kiếm nó trên google (tôi không thể đăng bất kỳ liên kết nào nữa, vì tôi là người mới ở đây: [), thêm lớp vào dự án của bạn và bạn có thể chỉ cần thay thế ProgressBar trước đó bằng mã này và có thanh tiến trình không xác định giòn:

final ButteryProgressBar progressBar = new ButteryProgressBar(this);
progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 24));

Bạn cũng có thể cần đơn giản hóa mã này:

final TypedArray ta = c.obtainStyledAttributes(attrs, R.styleable.ButteryProgressBar);
try {
    mBarColor = ta.getColor(R.styleable.ButteryProgressBar_barColor,
            c.getResources().getColor(android.R.color.holo_blue_light));
    mSolidBarHeight = ta.getDimensionPixelSize(
            R.styleable.ButteryProgressBar_barHeight,
            Math.round(DEFAULT_BAR_HEIGHT_DP * mDensity));
    mSolidBarDetentWidth = ta.getDimensionPixelSize(
            R.styleable.ButteryProgressBar_detentWidth,
            Math.round(DEFAULT_DETENT_WIDTH_DP * mDensity));
} finally {
    ta.recycle();
}

mã này:

mBarColor = c.getResources().getColor(android.R.color.holo_blue_light);
mSolidBarHeight = Math.round(DEFAULT_BAR_HEIGHT_DP * mDensity);
mSolidBarDetentWidth = Math.round(DEFAULT_DETENT_WIDTH_DP * mDensity);

Hy vọng tôi đã giúp :)


Phương pháp removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener) từ loại ViewTreeObserver bị phản đối
Frozen Crayon

@ArjunU. chúng ta nên sử dụng cái gì thay thế>
Patrick Geyer.


Tôi đã kiểm tra thanh tiến trình không xác định ( ButteryProgressBar) với ActionBarActivitynhưng nó không hoạt động. Làm cách nào để đặt thanh tiến trình không xác định bên dưới ActionBar/Toolbar? Đây là cách bố trí những gì tôi đang sử dụng: stackoverflow.com/a/26440880/1480019
user1480019

2
@GerritHoekstra: Trong trường hợp getSupportActionBar().getHeight()chức năng hoạt động, bạn gần như ở đó. Các progressBar.setY()chức năng thiết đặt vị trí tương đối so với phía trên cùng của màn hình, bao gồm cả thanh trạng thái. Vì vậy, những gì bạn phải làm là setY(supportActionBarHeight + Math.ceil(25 * context.getResources().getDisplayMetrics().density)). Thanh trạng thái cao 25px (mdpi) và chia tỷ lệ với độ cứng cao hơn (hdpi / xhdpi / ...). Hãy thử và cho tôi biết nếu nó hoạt động.
Antimonit

25

Mở rộng các Hoạt động từ lớp sau để có Thanh tiến trình ở trên cùng (bên dưới Thanh hành động) của mỗi và một getProgressBar()phương thức:

Lớp phụ huynh:

public abstract class ProgressActivity extends Activity {
    private ProgressBar mProgressBar;

    @Override
    public void setContentView(View view) {
        init().addView(view);
    }

    @Override
    public void setContentView(int layoutResID) {
        getLayoutInflater().inflate(layoutResID,init(),true);
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        init().addView(view,params);
    }

    private ViewGroup init(){
        super.setContentView(R.layout.progress);
        mProgressBar = (ProgressBar) findViewById(R.id.activity_bar);
        return (ViewGroup) findViewById(R.id.activity_frame);
    }

    protected ProgressBar getProgressBar(){
        return mProgressBar;
    }
}

Bố cục (process.xml):

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
    android:layout_width="match_parent" android:layout_height="match_parent">
<ProgressBar android:id="@+id/activity_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="-8dp"
    style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
    />
  <FrameLayout android:id="@+id/activity_frame"
      android:layout_width="match_parent"
      android:layout_height="fill_parent"
      />
</LinearLayout>

1
Nó hoạt động ... cho hầu hết các phần. Thanh tiến trình trông tách biệt với thanh tác vụ. Tôi đã phải thêm android:layout_marginTop="-8dp"vào ProgressBar để mô phỏng hiệu ứng "bóng đổ". Nhưng đối với phương pháp này, có lẽ sẽ hiệu quả hơn nếu thêm nó vào chính bố cục chính. Tuy nhiên, bây giờ nó hoạt động như dự định. Cảm ơn vì đã hack.
zubietaroberto

@zubietaroberto Có, Bạn có thể thêm nó vào bố cục chính nếu bạn chỉ sử dụng nó cho một hoạt động. Nếu bạn muốn nhiều hoạt động có tính năng này, bạn chỉ cần mở rộng lớp được hiển thị ở trên.
SD

1
Nó làm việc cho tôi, nhưng thanh tiến trình xuất hiện bên dưới máy chủ tab, làm cách nào để tôi có thể đặt nó ở trên máy chủ tab và dưới thanh tác vụ?
DeckyFx

4

Tôi đã biên dịch mã từ luồng này cũng như các luồng khác trên StackOverflow và tạo một dự án có thể được sử dụng để triển khai ButteryProgessbar cũng như "kéo xuống để làm mới". https://github.com/pauldmps/Gmail-like-Pull-Down-to-Refresh

Hãy sử dụng mã trong ứng dụng của bạn.

Một lời cảm ơn lớn đến các bạn.


3

Vui lòng sử dụng mã dưới đây. chỉ cần sử dụng một kiểu mặc định trong thanh tiến trình nhưstyle="?android:attr/progressBarStyleHorizontal"

<RelativeLayout 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"
    >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
    <ProgressBar 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleHorizontal"
        android:indeterminate="true"

        />

</RelativeLayout>

0

Chà, tôi đã làm điều gì đó tương tự cho một trong những ứng dụng dành cho thú cưng của mình và không chắc đó là cách duy nhất hay cách tốt nhất để làm điều đó, nhưng nó chắc chắn hoạt động.

Để bắt đầu, hãy sử dụng thanh tác vụ lớp phủ và sau đó đặt nền có thể vẽ thành "null" để thanh tác vụ lớp phủ trong suốt.

Bây giờ trong bố cục hoạt động của bạn, hãy đặt lề trên cho chế độ xem gốc của bạn thành "chiều cao thanh tác vụ" Bạn có thể làm như thế này.

<RelativeLayout
    ...
    android:layout_marginTop="?android:attr/actionBarSize" />

Giờ đây, hành động sẽ không ẩn bất kỳ nội dung hoạt động nào của bạn.

Điều tiếp theo bạn phải làm bây giờ là - thêm chế độ xem tiêu đề trên đầu chế độ xem gốc của bạn với chiều cao bằng với thanh tác vụ. Đặt màu nền cho nó. Bây giờ đây sẽ là màu của thanh tác vụ của bạn và vì thanh tác vụ này căn chỉnh hoàn hảo trên pf trên cùng của chế độ xem tiêu đề này.

Giờ đây, bạn có thể dễ dàng đặt một thanh tiến trình vào dạng xem tiêu đề và căn chỉnh nó ở cuối dạng xem tiêu đề. Đối với người dùng, điều này sẽ trông như thể thanh tiến trình nằm trên chính thanh tác vụ, giống như chrome ..

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.