added read only poll

This commit is contained in:
Mariotaku Lee 2015-12-27 14:18:16 +08:00
parent ee48b63e63
commit c7edd7f647
90 changed files with 377 additions and 72 deletions

View File

@ -33,6 +33,7 @@ import com.bluelinelabs.logansquare.annotation.OnJsonParseComplete;
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
import org.apache.commons.lang3.math.NumberUtils;
import org.mariotaku.library.objectcursor.annotation.AfterCursorObjectCreated;
import org.mariotaku.library.objectcursor.annotation.CursorField;
import org.mariotaku.library.objectcursor.annotation.CursorObject;
@ -604,6 +605,30 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
return values.get(key);
}
public boolean getAsBoolean(@Nullable String key, boolean def) {
final ParcelableBindingValue value = getValue(key);
if (value == null) return def;
return Boolean.parseBoolean(value.value);
}
public String getAsString(@Nullable String key, String def) {
final ParcelableBindingValue value = getValue(key);
if (value == null) return def;
return value.value;
}
public int getAsInteger(@Nullable String key, int def) {
final ParcelableBindingValue value = getValue(key);
if (value == null) return def;
return NumberUtils.toInt(value.value, def);
}
public long getAsLong(@Nullable String key, long def) {
final ParcelableBindingValue value = getValue(key);
if (value == null) return def;
return NumberUtils.toLong(value.value, def);
}
@Override
public String toString() {
return "ParcelableCardEntity{" +

View File

@ -19,9 +19,11 @@
package org.mariotaku.twidere.app;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
@ -37,6 +39,7 @@ import com.nostra13.universalimageloader.cache.disc.DiskCache;
import com.nostra13.universalimageloader.cache.disc.impl.ext.LruDiskCache;
import org.acra.annotation.ReportsCrashes;
import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.twidere.BuildConfig;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.activity.AssistLauncherActivity;
@ -45,6 +48,7 @@ import org.mariotaku.twidere.activity.MainHondaJOJOActivity;
import org.mariotaku.twidere.service.RefreshService;
import org.mariotaku.twidere.util.BugReporter;
import org.mariotaku.twidere.util.DebugModeUtils;
import org.mariotaku.twidere.util.ExternalThemeManager;
import org.mariotaku.twidere.util.MathUtils;
import org.mariotaku.twidere.util.StrictModeUtils;
import org.mariotaku.twidere.util.TwidereBugReporter;
@ -156,6 +160,23 @@ public class TwidereApplication extends MultiDexApplication implements Constants
reloadConnectivitySettings();
registerActivityLifecycleCallbacks(getApplicationModule().getActivityTracker());
final IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
packageFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
final String[] packages = getPackageManager().getPackagesForUid(uid);
final ExternalThemeManager manager = getApplicationModule().getExternalThemeManager();
if (ArrayUtils.contains(packages, manager.getEmojiPackageName())) {
manager.reloadEmojiPreferences();
}
}
}, packageFilter);
}
private void initDebugMode() {
@ -205,18 +226,32 @@ public class TwidereApplication extends MultiDexApplication implements Constants
@Override
public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) {
if (KEY_REFRESH_INTERVAL.equals(key)) {
stopService(new Intent(this, RefreshService.class));
startRefreshServiceIfNeeded(this);
} else if (KEY_ENABLE_PROXY.equals(key) || KEY_CONNECTION_TIMEOUT.equals(key) || KEY_PROXY_HOST.equals(key)
|| KEY_PROXY_PORT.equals(key)) {
reloadConnectivitySettings();
} else if (KEY_CONSUMER_KEY.equals(key) || KEY_CONSUMER_SECRET.equals(key) || KEY_API_URL_FORMAT.equals(key)
|| KEY_AUTH_TYPE.equals(key) || KEY_SAME_OAUTH_SIGNING_URL.equals(key) || KEY_THUMBOR_ENABLED.equals(key)
|| KEY_THUMBOR_ADDRESS.equals(key) || KEY_THUMBOR_SECURITY_KEY.equals(key)) {
final SharedPreferences.Editor editor = preferences.edit();
editor.putLong(KEY_API_LAST_CHANGE, System.currentTimeMillis());
editor.apply();
switch (key) {
case KEY_REFRESH_INTERVAL:
stopService(new Intent(this, RefreshService.class));
startRefreshServiceIfNeeded(this);
break;
case KEY_ENABLE_PROXY:
case KEY_CONNECTION_TIMEOUT:
case KEY_PROXY_HOST:
case KEY_PROXY_PORT:
reloadConnectivitySettings();
break;
case KEY_CONSUMER_KEY:
case KEY_CONSUMER_SECRET:
case KEY_API_URL_FORMAT:
case KEY_AUTH_TYPE:
case KEY_SAME_OAUTH_SIGNING_URL:
case KEY_THUMBOR_ENABLED:
case KEY_THUMBOR_ADDRESS:
case KEY_THUMBOR_SECURITY_KEY:
final Editor editor = preferences.edit();
editor.putLong(KEY_API_LAST_CHANGE, System.currentTimeMillis());
editor.apply();
break;
case KEY_EMOJI_SUPPORT:
getApplicationModule().getExternalThemeManager().initEmojiSupport();
break;
}
}

View File

@ -1157,7 +1157,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
mediaPreview.displayMedia();
}
if (TwitterCardUtils.isCardSupported(status.card)) {
if (TwitterCardUtils.isCardSupported(status)) {
final Point size = TwitterCardUtils.getCardSize(status.card);
twitterCard.setVisibility(View.VISIBLE);
if (size != null) {
@ -1165,7 +1165,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
} else {
twitterCard.setCardSize(0, 0);
}
final Fragment cardFragment = TwitterCardUtils.createCardFragment(status.card);
final Fragment cardFragment = TwitterCardUtils.createCardFragment(status);
final FragmentManager fm = fragment.getChildFragmentManager();
if (cardFragment != null && !FragmentManagerTrojan.isStateSaved(fm)) {
final FragmentTransaction ft = fm.beginTransaction();
@ -1324,6 +1324,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
translateLabelView.setTextSize(defaultTextSize * 0.85f);
translateResultView.setTextSize(defaultTextSize * 1.05f);
repliesCountView.setTextSize(defaultTextSize * 1.25f);
retweetsCountView.setTextSize(defaultTextSize * 1.25f);
favoritesCountView.setTextSize(defaultTextSize * 1.25f);

View File

@ -19,19 +19,31 @@
package org.mariotaku.twidere.fragment.support.card;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.TableLayout;
import android.widget.TextView;
import org.apache.commons.lang3.math.NumberUtils;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.fragment.support.BaseSupportFragment;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatus.ParcelableCardEntity;
import org.mariotaku.twidere.util.support.ViewSupport;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -42,12 +54,15 @@ import java.util.regex.Pattern;
public class CardPollFragment extends BaseSupportFragment {
public static final Pattern PATTERN_POLL_TEXT_ONLY = Pattern.compile("poll([\\d]+)choice_text_only");
private LinearLayout mPollChoices;
private TableLayout mPollContainer;
private Button mVoteButton;
private TextView mPollSummary;
public static CardPollFragment show(ParcelableCardEntity card) {
public static CardPollFragment show(ParcelableStatus status) {
final CardPollFragment fragment = new CardPollFragment();
final Bundle args = new Bundle();
args.putParcelable(EXTRA_CARD, card);
args.putParcelable(EXTRA_STATUS, status);
args.putParcelable(EXTRA_CARD, status.card);
fragment.setArguments(args);
return fragment;
}
@ -59,25 +74,15 @@ public class CardPollFragment extends BaseSupportFragment {
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ParcelableCardEntity card = getArguments().getParcelable(EXTRA_CARD);
assert card != null && card.name != null;
final Matcher matcher = PATTERN_POLL_TEXT_ONLY.matcher(card.name);
if (!matcher.matches()) throw new IllegalStateException();
final int choicesCount = NumberUtils.toInt(matcher.group(1));
for (int i = 0; i < choicesCount; i++) {
TextView child = new TextView(getContext());
final int choiceIndex = i + 1;
final ParcelableCardEntity.ParcelableBindingValue label = card.getValue("choice" + choiceIndex + "_label");
final ParcelableCardEntity.ParcelableBindingValue value = card.getValue("choice" + choiceIndex + "_count");
child.setText(label.value + "(" + value.value + ")");
mPollChoices.addView(child);
}
initChoiceView(savedInstanceState);
}
@Override
public void onBaseViewCreated(View view, Bundle savedInstanceState) {
super.onBaseViewCreated(view, savedInstanceState);
mPollChoices = (LinearLayout) view.findViewById(R.id.poll_choices);
mPollContainer = (TableLayout) view.findViewById(R.id.poll_container);
mVoteButton = (Button) view.findViewById(R.id.vote);
mPollSummary = (TextView) view.findViewById(R.id.poll_summary);
}
@Nullable
@ -85,4 +90,133 @@ public class CardPollFragment extends BaseSupportFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_card_poll, container, false);
}
@Override
protected void fitSystemWindows(Rect insets) {
// No-op
}
private void initChoiceView(@Nullable Bundle savedInstanceState) {
final ParcelableCardEntity card = getCard();
final ParcelableStatus status = getStatus();
final int choicesCount = getChoicesCount(card);
final LayoutInflater inflater = getLayoutInflater(savedInstanceState);
int votesSum = 0;
final boolean countsAreFinal = card.getAsBoolean("counts_are_final", false);
final boolean showResult = countsAreFinal || status.account_id == status.user_id;
for (int i = 0; i < choicesCount; i++) {
final int choiceIndex = i + 1;
votesSum += card.getAsInteger("choice" + choiceIndex + "_count", 0);
}
final View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
for (int i = 0, j = mPollContainer.getChildCount(); i < j; i++) {
final View pollItem = mPollContainer.getChildAt(i);
final RadioButton choiceRadioButton = (RadioButton) pollItem.findViewById(R.id.choice_button);
choiceRadioButton.setChecked(v == pollItem);
}
}
};
final int color = ContextCompat.getColor(getContext(), R.color.material_light_blue_a200);
final float radius = getResources().getDimension(R.dimen.element_spacing_small);
for (int i = 0; i < choicesCount; i++) {
final View pollItem = inflater.inflate(R.layout.layout_poll_item, mPollContainer, false);
final TextView choicePercentView = (TextView) pollItem.findViewById(R.id.choice_percent);
final TextView choiceLabelView = (TextView) pollItem.findViewById(R.id.choice_label);
final RadioButton choiceRadioButton = (RadioButton) pollItem.findViewById(R.id.choice_button);
final int choiceIndex = i + 1;
final String label = card.getAsString("choice" + choiceIndex + "_label", null);
final int value = card.getAsInteger("choice" + choiceIndex + "_count", 0);
if (label == null) throw new NullPointerException();
final float choicePercent = votesSum == 0 ? 0 : value / (float) votesSum;
choiceLabelView.setText(label);
ViewSupport.setBackground(choiceLabelView, new PercentDrawable(choicePercent, radius, color));
choicePercentView.setText(String.format("%d%%", Math.round(choicePercent * 100)));
pollItem.setOnClickListener(clickListener);
if (showResult) {
choicePercentView.setVisibility(View.VISIBLE);
choiceRadioButton.setVisibility(View.GONE);
} else {
choicePercentView.setVisibility(View.GONE);
choiceRadioButton.setVisibility(View.VISIBLE);
}
mPollContainer.addView(pollItem);
}
if (showResult) {
mVoteButton.setVisibility(View.GONE);
} else {
mVoteButton.setVisibility(View.VISIBLE);
}
final String nVotes = getResources().getQuantityString(R.plurals.N_votes, votesSum, votesSum);
mPollSummary.setText(getString(R.string.poll_summary_format, nVotes, "final result"));
}
private int getChoicesCount(ParcelableCardEntity card) {
final Matcher matcher = PATTERN_POLL_TEXT_ONLY.matcher(card.name);
if (!matcher.matches()) throw new IllegalStateException();
return NumberUtils.toInt(matcher.group(1));
}
private ParcelableCardEntity getCard() {
final ParcelableCardEntity card = getArguments().getParcelable(EXTRA_CARD);
assert card != null && card.name != null;
return card;
}
private ParcelableStatus getStatus() {
return getArguments().getParcelable(EXTRA_STATUS);
}
private static class PercentDrawable extends Drawable {
private final Paint mPaint;
private final RectF mBounds;
private final float mPercent;
private final float mRadius;
PercentDrawable(float percent, float radius, int color) {
mPercent = percent;
mRadius = radius;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(color);
mBounds = new RectF();
}
@Override
public void draw(Canvas canvas) {
canvas.drawRoundRect(mBounds, mRadius, mRadius, mPaint);
}
@Override
protected void onBoundsChange(Rect bounds) {
mBounds.set(bounds);
mBounds.right = mBounds.left + mBounds.width() * mPercent;
super.onBoundsChange(bounds);
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
}

View File

@ -37,18 +37,39 @@ import java.util.Locale;
* Created by mariotaku on 15/12/20.
*/
public class ExternalThemeManager implements Constants {
private final Emoji emoji;
private final Application application;
private final SharedPreferencesWrapper preferences;
private Emoji emoji;
private String emojiPackageName;
public ExternalThemeManager(Application application, SharedPreferencesWrapper preferences) {
this.application = application;
this.preferences = preferences;
reloadEmojiPreferences();
}
public String getEmojiPackageName() {
return emojiPackageName;
}
public void reloadEmojiPreferences() {
final String emojiComponentName = preferences.getString(KEY_EMOJI_SUPPORT, null);
String packageName = null;
if (emojiComponentName != null) {
final ComponentName componentName = ComponentName.unflattenFromString(emojiComponentName);
if (componentName != null) {
packageName = componentName.getPackageName();
emojiPackageName = componentName.getPackageName();
}
}
emoji = new Emoji(application, packageName);
initEmojiSupport();
}
public void initEmojiSupport() {
if (emojiPackageName == null) {
emojiPackageName = null;
return;
}
emoji = new Emoji(application, emojiPackageName);
}
@NonNull

View File

@ -50,7 +50,7 @@ public abstract class TwitterCardFragmentFactory {
return CardBrowserFragment.show(player_url.value);
}
public static Fragment createCardPollFragment(ParcelableCardEntity card) {
return CardPollFragment.show(card);
public static Fragment createCardPollFragment(ParcelableStatus status) {
return CardPollFragment.show(status);
}
}

View File

@ -23,10 +23,9 @@ import android.graphics.Point;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import org.apache.commons.lang3.math.NumberUtils;
import org.mariotaku.twidere.fragment.support.card.CardPollFragment;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatus.ParcelableCardEntity;
import org.mariotaku.twidere.model.ParcelableStatus.ParcelableCardEntity.ParcelableBindingValue;
/**
* Created by mariotaku on 15/1/1.
@ -40,8 +39,9 @@ public class TwitterCardUtils {
public static final String CARD_NAME_ANIMATED_GIF = "animated_gif";
@Nullable
public static Fragment createCardFragment(ParcelableCardEntity card) {
if (card.name == null) return null;
public static Fragment createCardFragment(ParcelableStatus status) {
final ParcelableCardEntity card = status.card;
if (card == null || card.name == null) return null;
if (CARD_NAME_PLAYER.equals(card.name)) {
final Fragment playerFragment = sFactory.createPlayerFragment(card);
if (playerFragment != null) return playerFragment;
@ -55,36 +55,32 @@ public class TwitterCardUtils {
if (playerFragment != null) return playerFragment;
return TwitterCardFragmentFactory.createGenericPlayerFragment(card);
} else if (CardPollFragment.isPoll(card.name)) {
return TwitterCardFragmentFactory.createCardPollFragment(card);
return TwitterCardFragmentFactory.createCardPollFragment(status);
}
return null;
}
public static Point getCardSize(ParcelableCardEntity card) {
final ParcelableBindingValue player_width = ParcelableCardEntity.getValue(card, "player_width");
final ParcelableBindingValue player_height = ParcelableCardEntity.getValue(card, "player_height");
if (player_width != null && player_height != null) {
final int width = NumberUtils.toInt(String.valueOf(player_width.value), -1);
final int height = NumberUtils.toInt(String.valueOf(player_height.value), -1);
if (width > 0 && height > 0) {
return new Point(width, height);
}
final int playerWidth = card.getAsInteger("player_width", -1);
final int playerHeight = card.getAsInteger("player_height", -1);
if (playerWidth > 0 && playerHeight > 0) {
return new Point(playerWidth, playerHeight);
}
return null;
}
public static boolean isCardSupported(ParcelableCardEntity card) {
if (card == null || card.name == null) return false;
switch (card.name) {
public static boolean isCardSupported(ParcelableStatus status) {
if (status.card == null || status.card.name == null) return false;
switch (status.card.name) {
case CARD_NAME_PLAYER: {
return ParcelableCardEntity.getValue(card, "player_stream_url") == null;
return ParcelableCardEntity.getValue(status.card, "player_stream_url") == null;
}
case CARD_NAME_AUDIO: {
return true;
}
}
if (CardPollFragment.isPoll(card.name)) {
if (CardPollFragment.isPoll(status.card.name)) {
return true;
}
return false;

View File

@ -54,18 +54,16 @@ public class TwitterCardContainer extends FrameLayout {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
final int measuredHeight = MeasureSpec.getSize(heightMeasureSpec);
final int height;
if (mCardWidth != 0 && mCardHeight != 0) {
height = Math.round(measuredWidth * (mCardHeight / (float) mCardWidth));
} else {
height = measuredHeight;
if (mCardWidth <= 0 || mCardHeight <= 0) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
final int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
final int measuredHeight = Math.round(measuredWidth * (mCardHeight / (float) mCardWidth));
final int newWidthMeasureSpec = MeasureSpec.makeMeasureSpec(measuredWidth, MeasureSpec.EXACTLY);
final int newHeightMeasureSpec;
if (height != 0) {
newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
if (measuredHeight != 0) {
newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY);
} else {
newHeightMeasureSpec = heightMeasureSpec;
}

0
twidere/src/main/res-localized/values-ar/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-ast/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-ca/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-cs/strings.xml Executable file → Normal file
View File

0
twidere/src/main/res-localized/values-da/strings.xml Executable file → Normal file
View File

View File

0
twidere/src/main/res-localized/values-de/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-el/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-es/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-fa/strings.xml Executable file → Normal file
View File

View File

0
twidere/src/main/res-localized/values-fi/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-fr/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-hi/strings.xml Executable file → Normal file
View File

0
twidere/src/main/res-localized/values-hr/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-hu/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-in/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-it/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-iw/strings.xml Executable file → Normal file
View File

0
twidere/src/main/res-localized/values-ja/strings.xml Executable file → Normal file
View File

View File

0
twidere/src/main/res-localized/values-ko/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-ms/strings.xml Executable file → Normal file
View File

0
twidere/src/main/res-localized/values-nl/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-no/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-pl/strings.xml Executable file → Normal file
View File

View File

0
twidere/src/main/res-localized/values-pt/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-ru/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-sv/strings.xml Executable file → Normal file
View File

0
twidere/src/main/res-localized/values-th/strings.xml Executable file → Normal file
View File

0
twidere/src/main/res-localized/values-tr/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-uk/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-vi/strings.xml Executable file → Normal file
View File

View File

View File

0
twidere/src/main/res-localized/values-zh/strings.xml Executable file → Normal file
View File

View File

View File

View File

@ -18,14 +18,36 @@
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/fragment_card_poll"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/poll_choices"
<TableLayout
android:id="@+id/poll_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
android:padding="@dimen/element_spacing_normal"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<Button
android:id="@+id/vote"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/vote"/>
<TextView
android:id="@+id/poll_summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/element_spacing_normal"
android:layout_marginStart="@dimen/element_spacing_normal"/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Twidere - Twitter client for Android
~
~ Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<TableRow
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:clickable="true"
android:gravity="center_vertical"
android:padding="@dimen/element_spacing_small">
<TextView
android:id="@+id/choice_percent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:gravity="center_vertical|end"
android:paddingBottom="@dimen/element_spacing_small"
android:paddingLeft="@dimen/element_spacing_small"
android:paddingRight="@dimen/element_spacing_small"
android:paddingTop="@dimen/element_spacing_small"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"/>
<RadioButton
android:id="@+id/choice_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:clickable="false"
android:duplicateParentState="false"
android:focusable="false"/>
<TextView
android:id="@+id/choice_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:padding="@dimen/element_spacing_small"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"
tools:text="Choice"/>
</TableRow>

View File

@ -61,5 +61,9 @@
<item quantity="one">@string/N_likes_quantity_one</item>
<item quantity="other">@string/N_likes_quantity_other</item>
</plurals>
<plurals name="N_votes">
<item quantity="one">@string/N_votes_quantity_one</item>
<item quantity="other">@string/N_votes_quantity_other</item>
</plurals>
</resources>

View File

@ -748,6 +748,8 @@
<string name="N_favorites_quantity_other" tools:ignore="PluralsCandidate"><xliff:g id="count">%d</xliff:g> favorites</string>
<string name="N_likes_quantity_one" tools:ignore="PluralsCandidate"><xliff:g id="count">%d</xliff:g> like</string>
<string name="N_likes_quantity_other" tools:ignore="PluralsCandidate"><xliff:g id="count">%d</xliff:g> likes</string>
<string name="N_votes_quantity_one" tools:ignore="PluralsCandidate"><xliff:g id="count">%d</xliff:g> vote</string>
<string name="N_votes_quantity_other" tools:ignore="PluralsCandidate"><xliff:g id="count">%d</xliff:g> votes</string>
<string name="drafts_hint_messages">Your unsent tweets will save here</string>
<string name="keyboard_shortcuts">Keyboard shortcuts</string>
<string name="keyboard_shortcut_hint">Press keys</string>
@ -827,4 +829,7 @@
<string name="unknown_language">Unknown language</string>
<string name="system_default">System default</string>
<string name="emoji_support">Emoji support</string>
<string name="open_poll_in_official_app">Open poll in official app</string>
<string name="vote">Vote</string>
<string name="poll_summary_format"><xliff:g id="poll_count">%s</xliff:g> · <xliff:g id="poll_time_left">%s</xliff:g></string>
</resources>