diff --git a/app/build.gradle b/app/build.gradle index 5a4e7b2..fd7eee6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,8 +1,9 @@ apply plugin: 'com.android.application' +apply plugin: 'com.jakewharton.hugo' android { compileSdkVersion 23 - buildToolsVersion "23.0.3" + buildToolsVersion "23.0.2" defaultConfig { applicationId "com.csc.colloquium1" @@ -20,7 +21,10 @@ android { } dependencies { + compile 'com.android.support:recyclerview-v7:23.2.1' + compile 'com.android.support:cardview-v7:23.2.1' + compile 'com.android.support:appcompat-v7:23.2.1' compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' - compile 'com.android.support:appcompat-v7:23.3.0' + } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2a791e9..a1d5d11 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,5 +1,9 @@ + + xmlns:tools="http://schemas.android.com/tools" + package="com.lpaina.colloquium1"> + + + + + + + + + + + + diff --git a/app/src/main/java/com/lpaina/colloquium1/Card.java b/app/src/main/java/com/lpaina/colloquium1/Card.java new file mode 100644 index 0000000..5f4159f --- /dev/null +++ b/app/src/main/java/com/lpaina/colloquium1/Card.java @@ -0,0 +1,41 @@ +package com.lpaina.colloquium1; + +public class Card implements Cloneable { + public static final String TITLE_NAME = "TITLE"; + public static final String VALUE_NAME = "VALUE"; + public static final String[] NAMES = new String[]{TITLE_NAME, VALUE_NAME}; + private String title; + private String value; + + public Card() { + + } + + public Card(String title, String value) { + this.title = title; + this.value = value; + } + + @Override + protected Card clone() throws CloneNotSupportedException { + super.clone(); + return new Card(title, value); + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/app/src/main/java/com/lpaina/colloquium1/ChangeActivity.java b/app/src/main/java/com/lpaina/colloquium1/ChangeActivity.java new file mode 100644 index 0000000..2ad18f5 --- /dev/null +++ b/app/src/main/java/com/lpaina/colloquium1/ChangeActivity.java @@ -0,0 +1,70 @@ +package com.lpaina.colloquium1; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.text.Editable; +import android.text.TextWatcher; +import android.widget.EditText; +import android.widget.TextView; + +public class ChangeActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_change); + Intent intent = getIntent(); + String title = intent.getStringExtra(RVAdapter.CardViewHolder.TITLE); + String value = intent.getStringExtra(RVAdapter.CardViewHolder.VALUE); + final float value_float = Float.parseFloat(value.replace(",", ".")); + + final EditText editText1 = (EditText) findViewById(R.id.first_value); + final EditText editText2 = (EditText) findViewById(R.id.second_value); + + TextView textView1 = (TextView) findViewById(R.id.first_title); + TextView textView2 = (TextView) findViewById(R.id.second_title); + + editText1.setText("1"); + editText2.setText(value); + + textView1.setText("RUB"); + textView2.setText(title); + + editText1.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + float new_value = Float.parseFloat(String.valueOf(s)); + editText2.setText(Float.toString(value_float * new_value)); + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + + editText2.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + float new_value = Float.parseFloat(String.valueOf(s)); + editText1.setText(Float.toString(new_value / value_float)); + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + } +} diff --git a/app/src/main/java/com/lpaina/colloquium1/MainActivity.java b/app/src/main/java/com/lpaina/colloquium1/MainActivity.java new file mode 100644 index 0000000..f465696 --- /dev/null +++ b/app/src/main/java/com/lpaina/colloquium1/MainActivity.java @@ -0,0 +1,25 @@ +package com.lpaina.colloquium1; + +import android.app.Activity; +import android.database.Cursor; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; + +public class MainActivity extends Activity { + private static final String PATH_TO_COURSE = "http://www.cbr.ru/scripts/RssCurrency.asp"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + + Cursor cursor = getContentResolver().query(ReaderContentProvider.CONTENT_URI, + Card.NAMES, PATH_TO_COURSE, null, null); + + RVAdapter adapter = new RVAdapter(cursor); + recyclerView.setAdapter(adapter); + } +} diff --git a/app/src/main/java/com/lpaina/colloquium1/RSSParserTask.java b/app/src/main/java/com/lpaina/colloquium1/RSSParserTask.java new file mode 100644 index 0000000..ad656ea --- /dev/null +++ b/app/src/main/java/com/lpaina/colloquium1/RSSParserTask.java @@ -0,0 +1,78 @@ +package com.lpaina.colloquium1; + +import android.os.AsyncTask; +import android.util.Log; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import hugo.weaving.DebugLog; + +class RSSParserTask extends AsyncTask> { + + private static final String TAG = "RSSParserTask"; + + @Override + @DebugLog + protected List doInBackground(String... params) { + String query = params[0]; + ArrayList cards = null; + try { + URL url = new URL(query); + + XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); + factory.setNamespaceAware(false); + XmlPullParser parser = factory.newPullParser(); + parser.setInput(url.openStream(), "Windows-1251"); + + cards = new ArrayList<>(); + boolean started = false; + String info = null; + int eventType = parser.getEventType(); + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG) { + String name = parser.getName().toLowerCase(); + switch (name) { + case "item": + started = true; + break; + case "description": + if (started) { + info = parser.nextText(); + } + break; + } + } else if (eventType == XmlPullParser.END_TAG && parser.getName().equalsIgnoreCase("item")) { + started = false; + String[] strings = info.split("
"); + for (String string : strings) { + String[] values = string.split("-"); + cards.add(new Card(values[0].trim(), values[1].trim())); + } + } + + eventType = parser.next(); //move to next element + } + + } catch (XmlPullParserException | IOException e) { + Log.e(TAG, "doInBackground: ", e); + } + + Collections.sort(cards, new Comparator() { + @Override + public int compare(Card lhs, Card rhs) { + return lhs.getTitle().compareTo(rhs.getTitle()); + } + }); + return cards; + } + +} diff --git a/app/src/main/java/com/lpaina/colloquium1/RVAdapter.java b/app/src/main/java/com/lpaina/colloquium1/RVAdapter.java new file mode 100644 index 0000000..52fa224 --- /dev/null +++ b/app/src/main/java/com/lpaina/colloquium1/RVAdapter.java @@ -0,0 +1,85 @@ +package com.lpaina.colloquium1; + +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.support.v7.widget.CardView; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class RVAdapter extends RecyclerView.Adapter { + + private Cursor cursor; + + public RVAdapter(Cursor cursor) { + this.cursor = cursor; + } + + public void updateCursor(Cursor newCursor) { + if (cursor != null) { + cursor.close(); + } + cursor = newCursor; + } + + @Override + public int getItemCount() { + return cursor.getCount(); + } + + @Override + public CardViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recyclerview_item, viewGroup, false); + return new CardViewHolder(view); + } + + @Override + public void onBindViewHolder(CardViewHolder cardViewHolder, int i) { + if (cursor.moveToPosition(i)) { + cardViewHolder.title = cursor.getString(cursor.getColumnIndex(Card.TITLE_NAME)); + cardViewHolder.value = cursor.getString(cursor.getColumnIndex(Card.VALUE_NAME)); + + cardViewHolder.textViewTitle.setText(cardViewHolder.title); + cardViewHolder.textViewValue.setText(cardViewHolder.value); + + } + } + + public static class CardViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + public static final String TITLE = "title"; + public static final String VALUE = "value"; + + + final TextView textViewTitle; + final TextView textViewValue; + final CardView cardView; + + final Context context; + + int id; + String title; + String value; + + CardViewHolder(View itemView) { + super(itemView); + textViewTitle = (TextView) itemView.findViewById(R.id.title); + textViewValue = (TextView) itemView.findViewById(R.id.value); + cardView = (CardView) itemView.findViewById(R.id.card_view); + cardView.setOnClickListener(this); + context = itemView.getContext(); + } + + @Override + public void onClick(View v) { + Intent intent = new Intent(context, ChangeActivity.class); + intent.putExtra(TITLE, title); + intent.putExtra(VALUE, value); + context.startActivity(intent); + } + + } + +} diff --git a/app/src/main/java/com/lpaina/colloquium1/ReaderContentProvider.java b/app/src/main/java/com/lpaina/colloquium1/ReaderContentProvider.java new file mode 100644 index 0000000..6a6266c --- /dev/null +++ b/app/src/main/java/com/lpaina/colloquium1/ReaderContentProvider.java @@ -0,0 +1,83 @@ +package com.lpaina.colloquium1; + +import android.content.ContentProvider; +import android.content.ContentValues; +import android.content.UriMatcher; +import android.database.Cursor; +import android.database.MatrixCursor; +import android.net.Uri; +import android.support.annotation.NonNull; +import android.util.Log; + +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import hugo.weaving.DebugLog; + +@DebugLog +public class ReaderContentProvider extends ContentProvider { + private static final String AUTHORITY = "com.lpaina.colloquium1"; + public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); + + private static final int ENTRIES = 1; + private static final int ENTRIES_ID = 2; + + private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); + private static final String TAG = "ContentProvider"; + + static { + uriMatcher.addURI(AUTHORITY, "/entries", ENTRIES); + uriMatcher.addURI(AUTHORITY, "/entries/#", ENTRIES_ID); + } + + + public ReaderContentProvider() { + } + + @Override + public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public String getType(@NonNull Uri uri) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public Uri insert(@NonNull Uri uri, ContentValues values) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public boolean onCreate() { + return true; + } + + @Override + public Cursor query(@NonNull Uri uri, String[] projection, String selection, + String[] selectionArgs, String sortOrder) { + MatrixCursor cursor = new MatrixCursor(projection); + RSSParserTask task = new RSSParserTask(); + task.execute(selection); + + try { + List cards = task.get(5, TimeUnit.SECONDS); + for (Card card : cards) { + cursor.addRow(new String[]{card.getTitle(), card.getValue()}); + } + } catch (ExecutionException | InterruptedException | TimeoutException | NullPointerException e) { + Log.e(TAG, "query: cannot receive data", e); + return null; + } + return cursor; + } + + @Override + public int update(@NonNull Uri uri, ContentValues values, String selection, + String[] selectionArgs) { + throw new UnsupportedOperationException("Not yet implemented"); + } +} diff --git a/app/src/main/res/layout/activity_change.xml b/app/src/main/res/layout/activity_change.xml new file mode 100644 index 0000000..723015a --- /dev/null +++ b/app/src/main/res/layout/activity_change.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..0ae0266 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,20 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/recyclerview_item.xml b/app/src/main/res/layout/recyclerview_item.xml new file mode 100644 index 0000000..f2009db --- /dev/null +++ b/app/src/main/res/layout/recyclerview_item.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml new file mode 100644 index 0000000..63fc816 --- /dev/null +++ b/app/src/main/res/values-w820dp/dimens.xml @@ -0,0 +1,6 @@ + + + 64dp + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 3ab3e9c..d3bb5fd 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -3,4 +3,5 @@ #3F51B5 #303F9F #FF4081 + #FFFFFF diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..9e0a647 --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,6 @@ + + + 16dp + 16dp + 20sp + diff --git a/build.gradle b/build.gradle index 168f129..ac05823 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,8 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.0.0' + classpath 'com.android.tools.build:gradle:1.5.0' + classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files