Merge pull request #221 from KirkBushman/master
added PrecomputedFutureTextSetterCompat
This commit is contained in:
		
						commit
						b48b0889da
					
				| @ -66,6 +66,7 @@ ext { | ||||
|             'x-annotations'           : 'androidx.annotation:annotation:1.1.0', | ||||
|             'x-recycler-view'         : 'androidx.recyclerview:recyclerview:1.0.0', | ||||
|             'x-core'                  : 'androidx.core:core:1.0.2', | ||||
|             'x-appcompat'             : 'androidx.appcompat:appcompat:1.1.0', | ||||
|             'commonmark'              : "com.atlassian.commonmark:commonmark:$commonMarkVersion", | ||||
|             'commonmark-strikethrough': "com.atlassian.commonmark:commonmark-ext-gfm-strikethrough:$commonMarkVersion", | ||||
|             'commonmark-table'        : "com.atlassian.commonmark:commonmark-ext-gfm-tables:$commonMarkVersion", | ||||
|  | ||||
| @ -22,6 +22,7 @@ dependencies { | ||||
|         // @since 4.1.0 to allow PrecomputedTextSetterCompat | ||||
|         // note that this dependency must be added on a client side explicitly | ||||
|         compileOnly it['x-core'] | ||||
|         compileOnly it['x-appcompat'] | ||||
|     } | ||||
| 
 | ||||
|     deps['test'].with { | ||||
|  | ||||
| @ -0,0 +1,62 @@ | ||||
| package io.noties.markwon; | ||||
| 
 | ||||
| import android.text.Spanned; | ||||
| import android.util.Log; | ||||
| import android.widget.TextView; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.appcompat.widget.AppCompatTextView; | ||||
| import androidx.core.text.PrecomputedTextCompat; | ||||
| 
 | ||||
| import java.util.concurrent.Executor; | ||||
| 
 | ||||
| /** | ||||
|  * Please note this class requires `androidx.core:core` artifact being explicitly added to your dependencies. | ||||
|  * This is intended to be used in a RecyclerView. | ||||
|  * | ||||
|  * @see io.noties.markwon.Markwon.TextSetter | ||||
|  */ | ||||
| public class PrecomputedFutureTextSetterCompat implements Markwon.TextSetter { | ||||
| 
 | ||||
|     /** | ||||
|      * @param executor for background execution of text pre-computation, | ||||
|      *                 if not provided the standard, single threaded one will be used. | ||||
|      */ | ||||
|     @NonNull | ||||
|     public static PrecomputedFutureTextSetterCompat create(@Nullable Executor executor) { | ||||
|         return new PrecomputedFutureTextSetterCompat(executor); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static PrecomputedFutureTextSetterCompat create() { | ||||
|         return new PrecomputedFutureTextSetterCompat(null); | ||||
|     } | ||||
| 
 | ||||
|     @Nullable | ||||
|     private final Executor executor; | ||||
| 
 | ||||
|     @SuppressWarnings("WeakerAccess") | ||||
|     PrecomputedFutureTextSetterCompat(@Nullable Executor executor) { | ||||
|         this.executor = executor; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setText( | ||||
|             @NonNull TextView textView, | ||||
|             @NonNull Spanned markdown, | ||||
|             @NonNull TextView.BufferType bufferType, | ||||
|             @NonNull Runnable onComplete) { | ||||
| 
 | ||||
|         if (textView instanceof AppCompatTextView) { | ||||
|             ((AppCompatTextView) textView).setTextFuture(PrecomputedTextCompat.getTextFuture( | ||||
|                     markdown, ((AppCompatTextView) textView).getTextMetricsParamsCompat(), executor | ||||
|             )); | ||||
| 
 | ||||
|             onComplete.run(); | ||||
|         } else { | ||||
| 
 | ||||
|             throw new IllegalStateException("TextView provided is not a child of AppCompatTextView, cannot call setTextFuture()."); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -54,6 +54,7 @@ dependencies { | ||||
|     deps.with { | ||||
|         implementation it['x-recycler-view'] | ||||
|         implementation it['x-core'] // for precomputedTextCompat | ||||
|         implementation it['x-appcompat'] // for setTextFuture | ||||
|         implementation it['okhttp'] | ||||
|         implementation it['prism4j'] | ||||
|         implementation it['debug'] | ||||
|  | ||||
| @ -28,6 +28,7 @@ | ||||
|         <activity android:name=".simpleext.SimpleExtActivity" /> | ||||
|         <activity android:name=".customextension2.CustomExtensionActivity2" /> | ||||
|         <activity android:name=".precomputed.PrecomputedActivity" /> | ||||
|         <activity android:name=".precomputed.PrecomputedFutureActivity" /> | ||||
| 
 | ||||
|         <activity | ||||
|             android:name=".editor.EditorActivity" | ||||
|  | ||||
| @ -30,6 +30,7 @@ import io.noties.markwon.sample.inlineparser.InlineParserActivity; | ||||
| import io.noties.markwon.sample.latex.LatexActivity; | ||||
| import io.noties.markwon.sample.notification.NotificationActivity; | ||||
| import io.noties.markwon.sample.precomputed.PrecomputedActivity; | ||||
| import io.noties.markwon.sample.precomputed.PrecomputedFutureActivity; | ||||
| import io.noties.markwon.sample.recycler.RecyclerActivity; | ||||
| import io.noties.markwon.sample.simpleext.SimpleExtActivity; | ||||
| import io.noties.markwon.sample.table.TableActivity; | ||||
| @ -124,6 +125,10 @@ public class MainActivity extends Activity { | ||||
|                 activity = PrecomputedActivity.class; | ||||
|                 break; | ||||
| 
 | ||||
|             case PRECOMPUTED_FUTURE_TEXT: | ||||
|                 activity = PrecomputedFutureActivity.class; | ||||
|                 break; | ||||
| 
 | ||||
|             case EDITOR: | ||||
|                 activity = EditorActivity.class; | ||||
|                 break; | ||||
|  | ||||
| @ -23,6 +23,8 @@ public enum Sample { | ||||
| 
 | ||||
|     PRECOMPUTED_TEXT(R.string.sample_precomputed_text), | ||||
| 
 | ||||
|     PRECOMPUTED_FUTURE_TEXT(R.string.sample_precomputed_future_text), | ||||
| 
 | ||||
|     EDITOR(R.string.sample_editor), | ||||
| 
 | ||||
|     INLINE_PARSER(R.string.sample_inline_parser), | ||||
|  | ||||
| @ -0,0 +1,95 @@ | ||||
| package io.noties.markwon.sample.precomputed; | ||||
| 
 | ||||
| import android.app.Activity; | ||||
| import android.content.Context; | ||||
| import android.os.Bundle; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.recyclerview.widget.LinearLayoutManager; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| 
 | ||||
| import java.io.BufferedReader; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.io.InputStreamReader; | ||||
| 
 | ||||
| import io.noties.markwon.Markwon; | ||||
| import io.noties.markwon.PrecomputedFutureTextSetterCompat; | ||||
| import io.noties.markwon.recycler.MarkwonAdapter; | ||||
| import io.noties.markwon.sample.R; | ||||
| 
 | ||||
| public class PrecomputedFutureActivity extends Activity { | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onCreate(@Nullable Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_recycler); | ||||
| 
 | ||||
|         final Markwon markwon = Markwon.builder(this) | ||||
|                 .textSetter(PrecomputedFutureTextSetterCompat.create()) | ||||
|                 .build(); | ||||
| 
 | ||||
|         // create MarkwonAdapter and register two blocks that will be rendered differently | ||||
|         final MarkwonAdapter adapter = MarkwonAdapter.builder(R.layout.adapter_appcompat_default_entry, R.id.text) | ||||
|                 .build(); | ||||
| 
 | ||||
|         final RecyclerView recyclerView = findViewById(R.id.recycler_view); | ||||
|         recyclerView.setLayoutManager(new LinearLayoutManager(this)); | ||||
|         recyclerView.setHasFixedSize(true); | ||||
|         recyclerView.setAdapter(adapter); | ||||
| 
 | ||||
|         adapter.setMarkdown(markwon, loadReadMe(this)); | ||||
| 
 | ||||
|         // please note that we should notify updates (adapter doesn't do it implicitly) | ||||
|         adapter.notifyDataSetChanged(); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     private static String loadReadMe(@NonNull Context context) { | ||||
|         InputStream stream = null; | ||||
|         try { | ||||
|             stream = context.getAssets().open("README.md"); | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|         return readStream(stream); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     private static String readStream(@Nullable InputStream inputStream) { | ||||
| 
 | ||||
|         String out = null; | ||||
| 
 | ||||
|         if (inputStream != null) { | ||||
|             BufferedReader reader = null; | ||||
|             //noinspection TryFinallyCanBeTryWithResources | ||||
|             try { | ||||
|                 reader = new BufferedReader(new InputStreamReader(inputStream)); | ||||
|                 final StringBuilder builder = new StringBuilder(); | ||||
|                 String line; | ||||
|                 while ((line = reader.readLine()) != null) { | ||||
|                     builder.append(line) | ||||
|                             .append('\n'); | ||||
|                 } | ||||
|                 out = builder.toString(); | ||||
|             } catch (IOException e) { | ||||
|                 e.printStackTrace(); | ||||
|             } finally { | ||||
|                 if (reader != null) { | ||||
|                     try { | ||||
|                         reader.close(); | ||||
|                     } catch (IOException e) { | ||||
|                         // no op | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (out == null) { | ||||
|             throw new RuntimeException("Cannot read stream"); | ||||
|         } | ||||
| 
 | ||||
|         return out; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,16 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.appcompat.widget.AppCompatTextView | ||||
|     xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:id="@+id/text" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:layout_marginLeft="16dip" | ||||
|     android:layout_marginRight="16dip" | ||||
|     android:lineSpacingExtra="2dip" | ||||
|     android:paddingTop="8dip" | ||||
|     android:paddingBottom="8dip" | ||||
|     android:textAppearance="?android:attr/textAppearanceMedium" | ||||
|     android:textColor="#000" | ||||
|     android:textSize="16sp" | ||||
|     tools:text="Hello" /> | ||||
| @ -25,6 +25,8 @@ | ||||
| 
 | ||||
|     <string name="sample_precomputed_text"># \# PrecomputedText\n\nUsage of TextSetter and PrecomputedTextCompat</string> | ||||
| 
 | ||||
|     <string name="sample_precomputed_future_text"># \# PrecomputedFutureText\n\nUsage of TextSetter and PrecomputedFutureTextSetterCompat</string> | ||||
| 
 | ||||
|     <string name="sample_editor"># \# Editor\n\n`MarkwonEditor` sample usage to highlight user input in EditText</string> | ||||
| 
 | ||||
|     <string name="sample_inline_parser"># \# Inline Parser\n\nUsage of custom inline parser</string> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dimitry
						Dimitry