Fortschrittsleiste unter Aktionsleiste

79

Fragezusammenfassung: Wie kann ich eine ProgressBarIntegration in die ActionBar, wie in der Chrome App, erstellen?

Details: Sehen Sie sich diesen Screenshot von Chrome an:

Chrome für Android Screenshot

Ich möchte einfach so eine Aktionsleiste erstellen. Direkt unter der Aktionsleiste befindet sich eine ProgressBar, die entsprechend dem Laden der Seite gefüllt wird. Ich habe dieses Beispiel in vielen Apps wie Feedly gesehen, konnte jedoch keine eigene Implementierung erstellen. Ich habe versucht, Android-eigene APIs zu verwenden, um es zu erstellen:

@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);
}

Dieser Code bewirkt jedoch nur, dass die ProgressBar wie folgt über der Aktionsleiste angezeigt wird:

Mein App-Screenshot

Wie kann ich meine ProgressBar wie in der Chrome App unter der Aktionsleiste anzeigen lassen?

zubietaroberto
quelle
mögliche doppelte Frage dieser Antwort: stackoverflow.com/a/10755545/794088
Petey
Hast du die Lösung schon gefunden?
Eric
Screenshots für meine Oma
IlyaEremin

Antworten:

7

Dies ist jetzt ein natives Verhalten, das mit SwipeRefreshLayout abgerufen werden kann .

Sie können Ihre scrollbare Ansicht mit a umschließenSwipeRefreshLayout und müssen dann nur noch onRefresh- Ereignisse anhören :

@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);
}

Ein schönes und einfaches Tutorial finden Sie in diesem Blog .

AlexGuti
quelle
56

Ich war mit der oben akzeptierten Antwort nicht ganz zufrieden und habe selbst einige Nachforschungen angestellt.

Der Trick, den sie meiner Meinung nach verwendet haben, besteht darin, dass sie die Draufsicht in der aufgerufenen Ansichtshierarchie abgerufen DecorViewund dort den Fortschrittsbalken hinzugefügt haben. Auf diese Weise wird der Fortschrittsbalken sowohl über der Aktionsleiste als auch im Inhaltsbereich angezeigt. Beachten Sie, dass die Antwort des SD den Fortschrittsbalken in den Inhaltsbereich versetzt und dem tatsächlichen Inhalt Speicherplatz "stiehlt", was zu unerwarteten Ergebnissen führen kann.

Beispiel- Screenshots dieser Implementierung:

Fortschrittsanzeige

ProgressBarIndeterminate

Code

Fügen Sie diesen Code einfach in die onCreateMethode einer Aktivität ein und es sollte funktionieren:

// 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);
    }
});

Sie können mit dem Höhenargument von LayoutParams spielen, um die progressBar breiter oder schmaler einzustellen -10. Möglicherweise müssen Sie jedoch den Versatz anpassen .

Styling

Leider können Sie den hässlichen grauen Hintergrund des Fortschrittsbalkens sehen. Um es zu entfernen, funktioniert es nicht, einfach anhand der ID nach dem Hintergrund zu suchen und zu versuchen, ihn auszublenden. Um den Hintergrund zu entfernen, musste ich einen identischen Drawble der Systemversion erstellen und das Hintergrundelement entfernen.

TL; DR: Erstellen Sie eine Datei progress_horizontal_holo_no_background_light.xmlund fügen Sie diese Zeichnungsdatei ein:

<?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>

Kopieren Sie die entsprechenden PNG-Zeichen sdk/platforms/android-xx/data/res/drawable-xxx/in Ihr Projekt und fügen Sie sie im Code hinzu:

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

Extra: Unbestimmter Fortschrittsbalken

Pre-KitKat-Versionen unbestimmter Fortschrittsbalken sind ziemlich hässlich und verzögert. Sie können neue glatte progressBar namens herunterladen ButteryProgressBar. Suchen Sie einfach auf Google danach (ich kann keine weiteren Links posten, da ich neu hier bin: [), fügen Sie die Klasse zu Ihrem Projekt hinzu und Sie können einfach die vorherige ProgressBar durch diesen Code ersetzen und haben einen knusprigen unbestimmten Fortschrittsbalken:

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

Möglicherweise müssen Sie diesen Code auch vereinfachen:

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();
}

zu diesem Code:

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);

Hoffe ich habe geholfen :)

Antimonit
quelle
Die Methode removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener) vom Typ ViewTreeObserver ist veraltet
Frozen Crayon
@ArjunU. Was sollen wir stattdessen verwenden>
Patrick Geyer
@PatrickGeyer siehe stackoverflow.com/questions/16189525/…
Frozen Crayon
Ich habe den unbestimmten Fortschrittsbalken ( ButteryProgressBar) mit getestet, ActionBarActivityaber er funktioniert nicht. Wie kann ich einen unbestimmten Fortschrittsbalken unter das setzen ActionBar/Toolbar? Dies ist das Layout, das ich verwende: stackoverflow.com/a/26440880/1480019
user1480019
2
@GerritHoekstra: Falls die getSupportActionBar().getHeight()Funktion funktioniert, sind Sie fast da. Die progressBar.setY()Funktion legt die Position relativ zum oberen Bildschirmrand einschließlich der Statusleiste fest. Was Sie also tun müssen, ist zu setY(supportActionBarHeight + Math.ceil(25 * context.getResources().getDisplayMetrics().density)). Die Statusleiste ist 25px hoch (mdpi) und skaliert mit höherer Dichte (hdpi / xhdpi / ...). Probieren Sie es aus und sagen Sie mir, ob es funktioniert.
Antimonit
25

Erweitern Sie die Aktivitäten der folgenden Klasse, um oben (unter der Aktionsleiste) jeweils eine ProgressBar und eine getProgressBar()Methode zu haben:

Elternklasse:

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;
    }
}

Layout (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>
SD
quelle
1
Es funktioniert ... zum größten Teil. Die ProgressBar sieht getrennt von der Aktionsleiste aus. Ich musste das android:layout_marginTop="-8dp"zur ProgressBar hinzufügen , um den "Schatten" -Effekt zu simulieren. Bei dieser Methode ist es jedoch wahrscheinlich effizienter, sie dem Hauptlayout selbst hinzuzufügen. Doch jetzt funktioniert es wie beabsichtigt. Danke für den Hack.
zubietaroberto
@zubietaroberto Ja, Sie können es zum Hauptlayout hinzufügen, wenn Sie es nur für eine Aktivität verwenden. Wenn Sie möchten, dass mehrere Aktivitäten über diese Funktion verfügen, können Sie einfach die oben gezeigte Klasse erweitern.
SD
1
Es funktioniert für mich, aber der Fortschrittsbalken wird unter dem Tab-Host angezeigt. Wie kann ich ihn über dem Tabhost und unter der Aktionsleiste erstellen?
DeckyFx
4

Ich habe Code aus diesem Thread sowie anderen Threads in StackOverflow kompiliert und ein Projekt erstellt, mit dem ButteryProgessbar sowie "Pulldown zum Aktualisieren" implementiert werden können. https://github.com/pauldmps/Gmail-like-Pull-Down-to-Refresh

Fühlen Sie sich frei, den Code in Ihrer Anwendung zu verwenden.

Ein großes Dankeschön an euch.

Shantanu Paul
quelle
3

Bitte verwenden Sie den folgenden Code. Verwenden Sie einfach einen Standardstil in der Fortschrittsleiste alsstyle="?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>
Rang
quelle
0

Nun, ich habe etwas Ähnliches für eine meiner Haustier-Apps gemacht und bin mir nicht sicher, ob dies der einzige oder der beste Weg ist, aber es funktioniert definitiv.

Verwenden Sie zunächst eine Überlagerungsaktionsleiste und setzen Sie den zeichnbaren Hintergrund auf "null", damit die Überlagerungsaktionsleiste transparent ist.

Stellen Sie nun in Ihrem Aktivitätslayout den oberen Rand für Ihre Stammansicht auf "Höhe der Aktionsleiste" ein. Sie können dies folgendermaßen tun.

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

Jetzt wird durch die Aktion kein Aktivitätsinhalt mehr ausgeblendet.

Das nächste, was Sie jetzt tun müssen, ist - fügen Sie über Ihrer Stammansicht eine Kopfansicht mit der Höhe hinzu, die der Aktionsleiste entspricht. Stellen Sie eine Hintergrundfarbe ein. Dies wäre jetzt die Farbe Ihrer Aktionsleiste, und da die Aktionsleiste perfekt über dieser Kopfzeilenansicht ausgerichtet ist.

Jetzt können Sie einfach einen Fortschrittsbalken in die Kopfzeilenansicht einfügen und ihn am unteren Rand der Kopfzeilenansicht ausrichten. Für den Benutzer würde dies so aussehen, als ob sich der Fortschrittsbalken auf der Aktionsleiste selbst befindet, genau wie Chrom.

user2405598
quelle