diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6249a0e..52608a7 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -5,8 +5,8 @@
android:versionName="1.0" >
+ android:minSdkVersion="16"
+ android:targetSdkVersion="16" />
diff --git a/src/com/mhalka/qurantranslationdisplay/QuranReader.java b/src/com/mhalka/qurantranslationdisplay/QuranReader.java
index 1a89d81..93c55ff 100644
--- a/src/com/mhalka/qurantranslationdisplay/QuranReader.java
+++ b/src/com/mhalka/qurantranslationdisplay/QuranReader.java
@@ -53,6 +53,12 @@ public class QuranReader {
}
+ public String getChapterName() throws XPathExpressionException {
+ String expression = "string(/Chapter/@ChapterName)";
+ String text = xPath.compile(expression).evaluate(this.document);
+ return text;
+ }
+
public String getVerse(int num) throws XPathExpressionException {
String expression = "/Chapter/Verse[@VerseID='"+num+"']/text()";
String text = xPath.compile(expression).evaluate(this.document);
diff --git a/src/com/mhalka/qurantranslationdisplay/ShowAyah.java b/src/com/mhalka/qurantranslationdisplay/ShowAyah.java
index a097a8a..f036767 100644
--- a/src/com/mhalka/qurantranslationdisplay/ShowAyah.java
+++ b/src/com/mhalka/qurantranslationdisplay/ShowAyah.java
@@ -1,9 +1,13 @@
package com.mhalka.qurantranslationdisplay;
+import com.mhalka.qurantranslationdisplay.VerticalMarqueeTextView.ScrollingStoppedListener;
+
import android.app.Activity;
+import android.content.res.AssetManager;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.TranslateAnimation;
@@ -19,7 +23,11 @@ import android.widget.TextView;
*/
public class ShowAyah extends Activity {
+ private static int NUMBER_OF_MILISECONDS_TO_READ_ONE_LINE = 2500;
private VerticalMarqueeTextView ayah;
+ private TextView chapterName;
+ int currentChapter=1;
+ int currentVerse=1;
@Override
@@ -28,32 +36,83 @@ public class ShowAyah extends Activity {
setContentView(R.layout.activity_show_ayah);
ayah = (VerticalMarqueeTextView) findViewById(R.id.ayah);
+ chapterName = (TextView) findViewById(R.id.chapter_name_verse_number);
ayah.setMovementMethod(new ScrollingMovementMethod());
ayah.pauseMarquee();
- ayah.setDuration(150);
- ayah.setPixelYOffSet(10);
-
-
-//
-// DisplayMetrics dm = getResources().getDisplayMetrics();
-//
-// TranslateAnimation m_ta = new TranslateAnimation(0f,0f, dm.heightPixels, -1 * (dm.heightPixels));
-//
-// m_ta.setDuration(10000);
-// m_ta.setInterpolator(new LinearInterpolator());
-// m_ta.setRepeatCount(Animation.INFINITE);
-//
-//
-// ayah.startAnimation(m_ta);
+
+
+
+
+
+ ayah.setPixelYOffSet(ayah.getMaxLines() * ayah.getLineHeight());
+
+ ayah.setOnScrollingStoppedListener(new ScrollingStoppedListener() {
+
+ @Override
+ public void scrollingStopped(VerticalMarqueeTextView v) {
+ nextAyah();
+
+ }
+
+
+ });
+ showAyah(currentChapter, currentVerse);
- // Example of use of QuranReader
- // AssetManager assetManager = getAssets();
- // QuranReader reader = new QuranReader(assetManager, "quran_content");
- // reader.setChapter(2);
- // String verseText = reader.getVerse(16);
+
}
+
+ public void nextAyah() {
+ currentVerse++;
+ boolean verseExists = showAyah(currentChapter, currentVerse);
+ if (!verseExists) {
+ currentChapter++;
+ if(currentChapter > 114)currentChapter = 1;
+ currentVerse = 1;
+ showAyah(currentChapter, currentVerse);
+ }
+
+
+
+ }
+
+ public boolean showAyah(int chapter, int verse ) {
+
+
+
+ try {
+ ayah.setText("");
+ ayah.scrollTo(0, 0);
+ AssetManager assetManager = getAssets();
+ QuranReader reader = new QuranReader(assetManager, "quran_content");
+ reader.setChapter(chapter);
+ String verseText = reader.getVerse(verse);
+
+ if(verseText.equals("")) return false;
+ // Start or restart the Marquee if paused.
+
+
+ ayah.setText(verseText);
+ chapterName.setText(reader.getChapterName() + " " + String.valueOf(chapter) + ":" + String.valueOf(verse));
+ int duration = ayah.getLineCount() * NUMBER_OF_MILISECONDS_TO_READ_ONE_LINE;
+
+ // let them reflect a bit on one liners ! :) (also solves a bug )
+ if(duration <= NUMBER_OF_MILISECONDS_TO_READ_ONE_LINE) duration = 2 * NUMBER_OF_MILISECONDS_TO_READ_ONE_LINE;
+ if(ayah.getLineCount() > ayah.getMaxLines()) duration = ayah.getMaxLines() * NUMBER_OF_MILISECONDS_TO_READ_ONE_LINE;
+ ayah.setDuration(duration);
+ if (ayah.isPaused()) {
+ ayah.resumeMarquee();
+ }
+ return true;
+ }
+ catch (Exception e) {
+ Log.d("SHOWAYAH",e.toString());
+ return false;
+ }
+
+
+ }
@Override
protected void onResume() {
diff --git a/src/com/mhalka/qurantranslationdisplay/VerticalMarqueeTextView.java b/src/com/mhalka/qurantranslationdisplay/VerticalMarqueeTextView.java
new file mode 100644
index 0000000..fdbe697
--- /dev/null
+++ b/src/com/mhalka/qurantranslationdisplay/VerticalMarqueeTextView.java
@@ -0,0 +1,303 @@
+package com.mhalka.qurantranslationdisplay;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.TextView;
+
+public class VerticalMarqueeTextView extends TextView {
+
+ private boolean isUserScrolling, isPaused, stop;
+ private boolean isNotDrawn = true;
+ private final Activity activity;
+ private long duration;
+ private int pixelYOffSet;
+ private ScrollingStoppedListener onScrollingStoppedListener;
+
+ public ScrollingStoppedListener getOnScrollingStoppedListener() {
+ return onScrollingStoppedListener;
+ }
+
+ public void setOnScrollingStoppedListener(
+ ScrollingStoppedListener onScrollingStoppedListener) {
+ this.onScrollingStoppedListener = onScrollingStoppedListener;
+ }
+
+ /**
+ *
+ * Creates a vertically auto scrolling marquee of a TextView within an
+ * Activity. The (long) duration in milliseconds between calls to the next
+ * scrollBy(0, pixelYOffSet). Defaults to 65L. The (int) amount of Y pixels
+ * to scroll by defaults to 1.
+ *
+ */
+ public VerticalMarqueeTextView(Context context, AttributeSet attrs,
+ int defStyle) {
+ super(context, attrs, defStyle);
+
+ this.activity = (Activity) context;
+
+ init();
+ }
+
+ /**
+ *
+ * Creates a vertically auto scrolling marquee of a TextView within an
+ * Activity. The (long) duration in milliseconds between calls to the next
+ * scrollBy(0, pixelYOffSet). Defaults to 65L. The (int) amount of Y pixels
+ * to scroll by defaults to 1.
+ *
+ */
+ public VerticalMarqueeTextView(Context context, AttributeSet attrs) {
+
+ super(context, attrs);
+
+ this.activity = (Activity) context;
+
+ init();
+ }
+
+ /**
+ *
+ * Creates a vertically auto scrolling marquee of a TextView within an
+ * Activity. The (long) duration in milliseconds between calls to the next
+ * scrollBy(0, pixelYOffSet). Defaults to 65L. The (int) amount of Y pixels
+ * to scroll by defaults to 1.
+ *
+ */
+ public VerticalMarqueeTextView(Context context) {
+ super(context);
+
+ this.activity = (Activity) context;
+
+ init();
+ }
+
+ /**
+ * Initialize fields and start the marquee.
+ */
+ private void init() {
+ setDuration(65l);
+ setPixelYOffSet(1);
+
+ isUserScrolling = isPaused = stop = false;
+ setOnScrollingStoppedListener(new ScrollingStoppedListener() {
+
+ @Override
+ public void scrollingStopped(VerticalMarqueeTextView v) {
+ // dummy listener
+
+ }
+ });
+
+ startMarquee();
+
+ }
+
+ /**
+ * @return Returns the (long) duration in milliseconds between calls to the
+ * next scrollBy(0, pixelYOffSet).
+ */
+ public long getDuration() {
+ return duration;
+ }
+
+ /**
+ * @param duration
+ * Sets the (long) duration in milliseconds between calls to the
+ * next scrollBy(0, pixelYOffSet). Defaults to 65L if value is
+ * less than or equal to 0.
+ */
+ public void setDuration(long duration) {
+ if (duration <= 0) {
+ this.duration = 65l;
+ } else {
+ this.duration = duration;
+ }
+
+ }
+
+ /**
+ * @return Returns the (int) amount of Y pixels to scroll by.
+ */
+ public int getPixelYOffSet() {
+ return pixelYOffSet;
+ }
+
+ /**
+ * @param pixelYOffSet
+ * Sets the (int) amount of Y pixels to scroll by. Defaults to 1
+ * if value is less.
+ */
+ public void setPixelYOffSet(int pixelYOffSet) {
+ if (pixelYOffSet < 1) {
+ this.pixelYOffSet = 1;
+ } else {
+ this.pixelYOffSet = pixelYOffSet;
+ }
+ }
+
+ /**
+ * Starts the marquee. May only be called once.
+ */
+ private void startMarquee() {
+ new AutoScrollTextView().execute();
+ }
+
+ /**
+ * Stop the marquee. Cannot be restarted.
+ */
+ public void stopMarquee() {
+ stop = true;
+ }
+
+ /**
+ * Pauses the marquee.
+ */
+ public void pauseMarquee() {
+ isPaused = true;
+ }
+
+ /**
+ * Resumes marquee from a call to pauseMarquee();
+ */
+ public void resumeMarquee() {
+ isPaused = false;
+ }
+
+ /**
+ * @return Returns true if paused (including if paused do to user manually
+ * scrolling), false otherwise.
+ */
+ public boolean isPaused() {
+ if (isPaused || isUserScrolling) {
+ return true;
+ }
+ return false;
+ }
+
+ private class AutoScrollTextView extends AsyncTask {
+
+ private int pixelCount;
+
+ @Override
+ protected Void doInBackground(Void... params) {
+
+ // Check to see if the VMTV has been drawn to get proper sizing.
+ while (textViewNotDrawn()) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ // Changing stop to true will permanently cancel autoscrolling.
+ // Cannot be restarted.
+ while (!stop) {
+
+ // Allows scrolling to resume after VMTV has been released.
+ if (!(VerticalMarqueeTextView.this).isPressed()
+ && isUserScrolling && !isPaused) {
+ isUserScrolling = false;
+ }
+
+ while (!isUserScrolling && !stop && !isPaused) {
+
+ // Sleep duration amount between scrollBy pixelYOffSet
+ try {
+ Thread.sleep(duration);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ activity.runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+
+ // If the user is manually scrolling pause the auto
+ // scrolling marquee
+ if ((VerticalMarqueeTextView.this).isPressed()) {
+
+ isUserScrolling = true;
+
+ } else { // Otherwise auto scroll marquee
+
+ // if VMTV has reached or exceeded the last
+ // Y pixel scroll back to top
+ int scrolly = (VerticalMarqueeTextView.this)
+ .getScrollY();
+
+
+ if (pixelCount < (getMaxLines() * getLineHeight()) || scrolly >= pixelCount) {
+
+ /*
+ * (VerticalMarqueeTextView.this).scrollTo(0,
+ * 0);
+ */
+ (VerticalMarqueeTextView.this)
+ .pauseMarquee();
+ (VerticalMarqueeTextView.this).onScrollingStoppedListener
+ .scrollingStopped(VerticalMarqueeTextView.this);
+
+
+ } else { // Otherwise scroll by the pixelYOffSet
+
+ (VerticalMarqueeTextView.this).scrollBy(0,
+ pixelYOffSet);
+ }
+
+ (VerticalMarqueeTextView.this).invalidate();
+ }
+
+ }
+ });
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void onProgressUpdate(Void... values) {
+ // TODO Auto-generated method stub
+ super.onProgressUpdate(values);
+ }
+
+ private boolean textViewNotDrawn() {
+
+ activity.runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+ // Checks to see if VMTV has been drawn.
+ // In theory line count should be greater than 0 if drawn.
+ if ((VerticalMarqueeTextView.this).getLineCount() > 0) {
+ // Calculate the total pixel height that needs to be
+ // scrolled.
+ // May need additional calculations if there is
+ // additional padding.
+ pixelCount = (VerticalMarqueeTextView.this)
+ .getLineHeight()
+ * (VerticalMarqueeTextView.this).getLineCount();
+ isNotDrawn = false;
+ }
+
+ }
+ });
+
+ return isNotDrawn;
+ }
+
+ }
+
+ public interface ScrollingStoppedListener {
+ public void scrollingStopped(VerticalMarqueeTextView v);
+ }
+
+}
\ No newline at end of file