[OFFEN] ClickListener in ViewPager (dynamischer Seitenaufruf)

bowser36

bowser36

Neues Mitglied
3
So ich mal wieder.
Mein ViewPager läuft jetzt und ich kann auch Intents übergeben. Jetzt stehe ich vor dem nächsten Problem. Ich will durch einen ClickListener festlegen, welches HTML-File als nächste Page in die View geladen wird. Ich habe 8 Pages, jede wird durch ein HTML-File mit Text und ggf. Bildern gefüttert. Ich möchte jetzt z.B. die Möglichkeit haben, bei Seite 4 auszuwählen ob danach Seite 6 oder 7 kommt. Wie kann ich jetzt einen ClickListener einbinden? Die Listener müssten irgendwie mit den HTML-Files verlinkt werden, evtl. auf ein Image was im HTML-File verlinkt ist. Geht das?

Muss der ViewPager immer drei aktuellen drei Seiten/Pages kennen? Also die vorige, die aktuelle und die folgende?

Könnte ich die neu ausgewählte Seite im aktuellen ViewPager anzeigen lassen oder muss man dazu einen neuen Pager, Fragment oder Activity anlegen/aufrufen?

Ich habe für die einzelnen Seiten eine Klasse angelegt, in der sich diverse Attribute befinden, womit die "Auswahlmethoden" arbeiten. Kann man das evtl. dazu nutzen einen Listener anzulegen?

Thx schonmal b36
 
Keiner ne Idee oder gehe ich da etwas falsch an die Sache heran?
 
Hallo Bowser36,


Keiner ne Idee oder gehe ich da etwas falsch an die Sache heran?

bitte nicht pushen - auch wenn es Dir unter den Nägeln brennt :
Ich denke , die Meisten waren gestern bei dem schönen Wetter eher draußen und grillen :)
(Das Forum ist nachwievor eine private Veranstaltung)

Ich muss ehrlich gestehen , so ganz verstehe ich nicht, was du möchtest .

Wenn du doch in deinem Layout einen Button hast - was hindert dich denn daran, dort zu bestimmen
welches View als nächstes kommt ?

Was hast du denn in deinen Elementen der PageViewer drinne ?
Ein Layout mit Elementen und einem WebView ? Nur ein WebView ?
Wo sitzt dein Button ? Was machst du bis jetzt mit dem ?

Eigentlich fehlt für die Beantwortung deiner Frage der Anriss Deines Konzeptes und der Code.
 
Zuletzt bearbeitet:
Es soll eine Buch-App werden und ich bin bis jetzt so unterwegs:
In den Assets habe ich die HTML Files, die die Texte für die Views beinhalten. In den HTML Files sind auch Source-Links für evtl. angezeigte Bilder drin.
Gestartet wird von der MainActivity, wo man ein Buch auswählen kann, bei Click öffnet sich ein DialogFragment von wo aus das gewählte Buch als Objekt per Click an die TextActivity übergeben wird und dort angezeigt wird.
In der TextActivtiy befindet sich bis jetzt nur ein ViewPager der eine Webview beinhaltet, die die HTML Seiten ausgibt. In dieser Activity sollen halt bei Bedarf ClickListener existieren (z.B. für HTML File 2, 5 und 7). Das Problem ist, dass die Seiten nicht immer in gleicher Reihenfolge angezeigt werden. Die ClickListener müssten also an die HTML Files oder die Objekte gebunden werden.

TextActivty:

Code:
public class TextActivity extends FragmentActivity {

    Book selectedBook;
    ViewPager vPager;
    FragmentStatePagerAdapter adapter;
    String textsPath;

    //Beispiel Files für die WebView Anzeige
    String[] pages={
            "file:///android_asset/books\\der_maulwurf_grabowski\\texts\\part_1.html",
            "file:///android_asset/books\\der_maulwurf_grabowski\\texts\\part_2.html",
            "file:///android_asset/books\\der_maulwurf_grabowski\\texts\\part_3.html",
    };

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.text_activity);
        vPager = (ViewPager) findViewById(R.id.viewpager);

        Bundle data = getIntent().getExtras();
        Book bookToRead = data.getParcelable("Book");
        selectedBook = bookToRead;
        assert bookToRead != null;
        textsPath = bookToRead.getTextsPath();
        
        adapter = new FragmentStatePagerAdapter(getSupportFragmentManager()){

            @Override
            public int getCount() {
                return pages.length;
            }

            @Override
            public android.support.v4.app.Fragment getItem(int position) {
                return Pager.newInstance(pages[position]);
            }
        };
        vPager.setAdapter(adapter);
    }
}

ViewPager-Klasse:

Code:
public class Pager extends Fragment {
    WebView pagerWebView;
    String textPassage;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        
        View view = inflater.inflate(R.layout.pager_layout, container, false);
        pagerWebView = (WebView) view.findViewById(R.id.pagerfragment);
        pagerWebView.setWebViewClient(new WebViewClient());
        pagerWebView.loadUrl(textPassage);
        return view;
    }

    public static Pager newInstance(String passage){
        Pager f = new Pager();
        f.textPassage = passage;
        return f;
    }
}


Buch-Klasse:

Code:
public class Book implements Parcelable {


    public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel source) {
            return new Book(source);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };
    public String title;
    public int year;
    public String info;
    public String author;
    public String picsPath;
    public String textsPath;
    public String viewID;
    public ArrayList<StoryPart> storyparts;

    public Book() {storyparts = new ArrayList<StoryPart>();
    }

    protected Book(Parcel in) {
        this.title = in.readString();
        this.year = in.readInt();
        this.info = in.readString();
        this.author = in.readString();
        this.picsPath = in.readString();
        this.textsPath = in.readString();
        this.viewID = in.readString();
        this.storyparts = in.createTypedArrayList(StoryPart.CREATOR);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.title);
        dest.writeInt(this.year);
        dest.writeString(this.info);
        dest.writeString(this.author);
        dest.writeString(this.picsPath);
        dest.writeString(this.textsPath);
        dest.writeString(this.viewID);
        dest.writeTypedList(this.storyparts);

...
    }

TextActivity Layout-XML:

Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

Pager Layout-XML:

Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <WebView
        android:id="@+id/pagerfragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </WebView>

</LinearLayout>
 
Hallo Bow,

In dieser Activity sollen halt bei Bedarf ClickListener existieren (z.B. für HTML File 2, 5 und 7). Das Problem ist, dass die Seiten nicht immer in gleicher Reihenfolge angezeigt werden. Die ClickListener müssten also an die HTML Files oder die Objekte gebunden werden.

a) wohin soll der ClickListener ? auf einen Button ? ins Webview ?
b) Du kannst dir auch ein Array basteln , indem du die Reihenfolge festlegst
 
Der Listener soll wahrscheinlich ins WebView, ich denke auf ein Image.

Die Reihenfolge ist aber nicht fest, die soll sich ja immer verändern können. Ich denke man müsste das Array dann bei jedem Click neu oder ab der aktuellen Position mit den nächsten möglichen Seiten befüllen.
 
Moment :

Der Listener soll wahrscheinlich ins WebView, ich denke auf ein Image.

Der Listener hat nichts mit dem html image zu tun , sondern bezieht sich nur auf das View .
Wenn du es auf ein Image haben magst , dann musst du den html link abfangen (Webclient)

Die Reihenfolge ist aber nicht fest, die soll sich ja immer verändern können

Wer verändert sie denn ?
Du ? Das Programm mit Random ?

Für Beides kannst du ein Array verwenden und füllst es dementsprechend ...
 
Die Reihenfolge wird durch das ClickEvent (vom Nutzer bedient) verändert. Z.B. wird gefragt: "Soll jetzt Seite 6 oder 8 kommen?" --> 2 Buttons/Images und los geht die wilde Fahrt.

Hab gerade was gefunden im Netz. Buttons in html einbinden und mit JS an die Activity übergeben. Das wär doch was. Müsste ich halt doch JS nehmen, von was ich leider auch keine Ahnung habe.
[doublepost=1491839414,1491839311][/doublepost]also das ClickEvent ruft dann eine Methode auf die bestimmte Attribute des Buch Objektes vergleicht und dann die nächste Seite oder Seiten ausgibt.
 
Hab es jetzt mit den Buttons in den html-Files und Javascript erstmal hinbekommen. Jetzt stehe ich vor der nächsten Frage. Wenn ich jetzt dem Array, das die Pfadangaben der html-text-files für den ViewPager bereitstellt, neue Einträge hinzufüge, werden diese Seiten im Viewpager erst angezeigt, wenn ich alle Pages einmal durchgeswiped habe (bis zum Ende) und wieder zurück zu der Page gehe, die neu angezeigt werden soll. Wie kriege ich es hin, dass das Webview sofort aktualisiert wird?
 
Sorry ich meinte den Viewpager, nicht die Webview.
 
P.S Aber ein bisschen könntest du auch selbst die Doku studieren :)
glaub mir, das mache ich :)

Kenne auch beide Links schon, trotzdem natürlich vielen Dank für die bisherige Hilfe, bis jetzt habt ihr mich immer auf die richtige Fährte gebracht.

ich muss aber ehrlich sagen, dass ich bis jetzt glaube ich die wenigste Hilfe von developer.android bekommen habe. Irgendwie blicke ich da oft auch nicht so recht durch oder kann es nicht wirklich auf mein Projekt anwenden. Der Stackoverflow link scheint schon das richtige zu sein aber ich muss das erstmal richtig bei mir eingebaut bekommen.
 
Ich krieg's nicht hin, ich kapier nicht so recht wo oder wie ich den update Aufruf nach dem hinzufügen der weiteren Pages anlegen muss. Es klappt soweit, bis ich, nach dem Klick und dem hinzufügen der weiteren Pages zum Pager, versuche zur nächsten Seite zu swipen. Dann crasht die App und und im Logcat steht, dass der PagerAdapter nicht über die veränderten Daten informiert wurde. Beim Start der Activity wird die erste Seite in den Pager geladen und dann soll über Click in der Webview (auf einen html-Button) per JavaScript eine Methode im PagerAdapter ausgeführt werden, die die nächsten Seiten an den Pager übergibt. notifyDataSetChanged() geht jetzt aber nur über this. und dann kann die Methode aus dem Webinterface nicht mehr die Methode im PagerAdapter aufrufen. Ich komm irgendwie nicht vom Webinterface in den PagerAdapter.


Code:
public class PagerFragment extends Fragment {

WebView pagerWebView;
WebAppInterface JSInterface;
private static final String POSITION = "position";
private static final String PARTID = "partId";

public PagerFragment(){}

static PagerFragment newInstance(int position, String storyPart){
    PagerFragment pFrag = new PagerFragment();
    Bundle bundle = new Bundle();
    bundle.putInt(POSITION, position);
    bundle.putString(PARTID, storyPart);
    pFrag.setArguments(bundle);
    return pFrag;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.pager_layout, container, false);
    String storyPart = getArguments().getString(PARTID);
    int position = getArguments().getInt(POSITION);
    pagerWebView = (WebView) view.findViewById(R.id.pagerfragment);
    pagerWebView.setWebViewClient(new WebViewClient());
    pagerWebView.loadUrl(storyPart);

    // JS-Kommunikation____________________________________________________
    WebSettings webSettings = pagerWebView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    JSInterface = new WebAppInterface(this);
    pagerWebView.addJavascriptInterface(JSInterface, "Android");

    return view;
}
}

Code:
public class MyPagerAdapter extends FragmentStatePagerAdapter {

    private static final String TAG = "MyPAGErADAPTEr";
    Book bookToRead;
    static ArrayList<String> pages;
    static ArrayList<String> nextPages;
    static String textsPath;
    static ArrayList<StoryPart> storyParts;
    boolean firstStart = true;

    public MyPagerAdapter(FragmentManager fm) {super(fm);}

    public MyPagerAdapter(FragmentManager fm, Book selectedBook) {
        super(fm);
        bookToRead = selectedBook;
        pages = new ArrayList<>();
        textsPath = bookToRead.getTextsPath();
        storyParts = bookToRead.getStoryparts();
//        ps = new PartSelector(bookToRead);
        start();
    }

    @Override
    public int getCount() {
        return pages.size();
    }

    @Override
    public Fragment getItem(int position){
        return PagerFragment.newInstance(position, textsPath + pages.get(position));
    }

    public void start(){
        nextPages = new ArrayList<>();
        if(firstStart){
            for(StoryPart item : bookToRead.getStoryparts()){
                if(item.isStart){
                    Log.d("STARTinFOR", item.getFilename());
                    nextPages.add(item.getFilename());
                    firstStart = false;
                }
            }
        }
        pages.addAll(nextPages);
    }

    public static void decide(String action, String currentPage){
        for(StoryPart item : storyParts){
            if((!(item.getFilename().equalsIgnoreCase(currentPage))) && item.inBetween) nextPages.add(textsPath + item.getFilename());
        }
//        pages.addAll(nextPages);
        Log.d(TAG, "pages ist:" + pages.size());
        pages.addAll(nextPages);
        Log.d(TAG, "pages ist:" + pages.size());
    }
}

Code:
public class WebAppInterface {
Context mContext;
PagerFragment mp;
ArrayList<String> newParts;


public WebAppInterface(PagerFragment pager) {
    mp = pager;
}

// "JavaScript-Methoden" für die Nutzung in den HTML-Files
@JavascriptInterface
public void nextPages(String action, String page){
    MyPagerAdapter.decide(action, page);
}
}

Logcat:

E/InputEventReceiver: Exception dispatching input event.
E/MessageQueue-JNI: Exception in MessageQueue callback: handleReceiveCallback
E/MessageQueue-JNI: java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 1, found: 5 Pager id: com.example.max.infinistry:id/viewpager Pager class: class android.support.v4.view.ViewPager Problematic adapter: class com.example.max.infinistry.MyPagerAdapter
at android.support.v4.view.ViewPager.populate(ViewPager.java:1167)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1116)
at android.support.v4.view.ViewPager.smoothScrollTo(ViewPager.java:999)
at android.support.v4.view.ViewPager.scrollToItem(ViewPager.java:683)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:669)
at android.support.v4.view.ViewPager.onTouchEvent(ViewPager.java:2284)
at android.view.View.dispatchTouchEvent(View.java:10023)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2626)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2307)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:413)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1808)
at android.app.Activity.dispatchTouchEvent(Activity.java:3061)
at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:375)
at android.view.View.dispatchPointerEvent(View.java:10243)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4438)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4306)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3853)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3906)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3872)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3999)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3880)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4056)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3853)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3906)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3872)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3880)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3853)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6246)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6220)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6181)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6349)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:323)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
D/AndroidRuntime: Shutting down VM
 
Schick mir mal dein projekt bitte - ich schau es mir morgen mal an
(Heute ist Familie angesagt)

Vorweg : du hast da so Einiges miteinander "verwurschtelt". Der Pager ist zumindest nicht ganz konform
und das JavaScript sollte man im abgeleiteten WebViewClient nach PageLoad nachziehen

Du hast PN mit meiner email
 
Zuletzt bearbeitet:
Wenn ich die Fehlermeldung richtig verstehe, versuchst du die "page" 5 zu öffnen, der Adapter hat aber nur eine "page". Du muss den Adapter mit einer ArrayList befüllen, die alle "Seiten" umfasst. Wenn das am Anfang nicht von ohne weiteres geht, muss du den Adapter neu befüllen, und dann notifyDataSetChanged() aufrufen.
 
hab das Projekt jetzt ohne den ViewPager und nur mit einem normalen Webview gemacht. aber thx trotzdem
 

Ähnliche Themen

D
Antworten
23
Aufrufe
2.551
Data2006
D
Tiefkuehlpizza
Antworten
2
Aufrufe
956
Tiefkuehlpizza
Tiefkuehlpizza
N
  • no1Ltan
Antworten
12
Aufrufe
1.736
jogimuc
J
Zurück
Oben Unten