ProgressBar в панели действий
Резюме вопроса: Как сделать ProgressBar
интегрированным внутри ActionBar
, например, в приложении Chrome?
Детали: Посмотрите на этот снимок экрана из Chrome:
![Chrome for Android screenshot]()
Я хочу создать панель действий так же, как это. Просто под панелью действий есть ProgressBar, который заполняется в соответствии с загрузкой страницы. Я видел этот пример из многих приложений, таких как Feedly, но я не смог создать свою собственную реализацию. Я попытался использовать собственные API-интерфейсы Android для его создания:
@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);
}
Но этот код только заставляет ProgressBar показывать над панель действий, например:
![My App Screenshot]()
Итак, как я могу сделать свой ProgressBar в панели действий, например, в приложении Chrome?
Ответы
Ответ 1
Теперь это естественное поведение, которое можно получить с помощью SwipeRefreshLayout.
Вы можете обернуть прокручиваемое представление с помощью SwipeRefreshLayout
, а затем вам просто нужно прослушать onRefresh events:
@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);
}
Хороший и простой учебник можно найти в в этом блоге.
Ответ 2
Я не был полностью удовлетворен принятым ответом выше, поэтому сам сделал некоторые дополнительные исследования.
Трюк, который, как мне кажется, они использовали, заключается в том, что они отобрали верхний вид в иерархии представлений под названием DecorView
и добавили там индикатор выполнения. Таким образом, индикатор выполнения отображается как над панелью действий, так и с областью содержимого. Обратите внимание, что S.D. ответ помещает индикатор выполнения в область содержимого и "крадет" пространство из фактического содержимого, что может привести к неожиданным результатам.
Пример скриншотов этой реализации:
![ProgressBar]()
![ProgressBarIndeterminate]()
код
Просто поместите этот код в метод onCreate
некоторой активности, и он должен работать:
// 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.removeGlobalOnLayoutListener(this);
}
});
Вы можете играть с аргументом высоты LayoutParams, чтобы установить progressBar шире или уже, но вам, возможно, придется отрегулировать смещение -10
.
Стайлинг
К сожалению, вы можете увидеть уродливый серый фон индикатора выполнения. Чтобы удалить его, просто поиск фона по id и попытка скрыть его не работают. Чтобы удалить фон, мне пришлось создать идентичный вариант версии системы и удалить фоновый элемент.
TL; DR: создайте файл progress_horizontal_holo_no_background_light.xml
и вставьте его:
<?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>
Скопируйте соответствующие чертежи .png из sdk/platforms/android-xx/data/res/drawable-xxx/
в ваш проект, а затем в код, который вы можете добавить:
progressBar.setProgressDrawable(getResources().getDrawable(R.drawable.progress_horizontal_holo_no_background_light));
Дополнительно: Неопределенный индикатор выполнения
Pre-KitKat версии неопределенных индикаторов прогресса довольно уродливы и отстают.
Вы можете загрузить новый плавный progressBar с именем ButteryProgressBar
. Просто найдите его в google (я не могу размещать больше ссылок, потому что я здесь новый: [], добавьте класс в свой проект, и вы можете просто заменить предыдущий ProgressBar этим кодом и иметь хрустящий неопределенный индикатор выполнения:
final ButteryProgressBar progressBar = new ButteryProgressBar(this);
progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 24));
Вам также может потребоваться упростить этот код:
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();
}
к этому коду:
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);
Надеюсь, я помог:)
Ответ 3
Расширьте действия из следующего класса, чтобы иметь ProgressBar вверху (ниже ActionBar) каждого и метод getProgressBar()
:
Родительский класс:
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;
}
}
Макет (progress.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>
Ответ 4
Я скомпилировал код из этого потока, а также другие потоки в StackOverflow и создал проект, который можно использовать для реализации ButteryProgessbar, а также "pull down to refresh". https://github.com/pauldmps/Gmail-like-Pull-Down-to-Refresh
Не стесняйтесь использовать код в своем приложении.
Большое спасибо вам, ребята.
Ответ 5
Пожалуйста, используйте нижеприведенный код. просто используйте один стиль по умолчанию в строке выполнения как 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>
Ответ 6
Хорошо, я сделал что-то похожее для одного из моих приложений для домашних животных и не уверен, что это единственный способ или лучший способ сделать это, но он определенно работает.
Для начала используйте панель действий оверлея, а затем установите для фона значение "null" так, чтобы панель действия наложения была прозрачной.
Теперь в макете активности установите верхнее поле для корневого представления на "высоту панели действий". Вы можете сделать это следующим образом.
<RelativeLayout
...
android:layout_marginTop="?android:attr/actionBarSize" />
Теперь действие не скроет ваше содержимое.
Следующее, что вам нужно сделать сейчас - добавить заголовок в верхней части корневого представления с высотой, такой же, как панель действий. Установите для него цвет фона. Теперь это будет цвет вашей панели действий, а так как панель действий идеально выравнивается поверх этого заголовка.
Теперь вы можете легко установить индикатор выполнения в виде заголовка и выровнять его в нижней части заголовка. Для пользователя это выглядело бы так, как если бы индикатор выполнения находился на панели действий, точно так же, как хром..